Показать сообщение отдельно

  #284  
Старый 05.02.2008, 10:41
krypt3r
Познавший АНТИЧАТ
Регистрация: 27.04.2007
Сообщений: 1,044
С нами: 10021597

Репутация: 905


По умолчанию

Озадачился на днях генерацией словарика, содержащий только даты за определенный период. Также используются разные разделители, например, дата 2007.12.31:
Код:
20071231
2007/12/31
31.12.07
и т.д.
Набросал скриптик на перле, который просит 2 даты начальную и конечную. Так как мне влом было читать маны (перлдоки ) по модулям Date, взял за основу алгоритм вычисления юлианского дня из астрономии (тем более уже был код, тока на паскале =) ). Вот сам код:
Код:
#!/usr/bin/perl

$argc = $#ARGV + 1;

&usage () unless ($argc == 2);

use Julian;
use lib ".";

%mon =
(
  "01" => "january",
  "02" => "february",
  "03" => "march",
  "04" => "april",
  "05" => "may",
  "06" => "june",
  "07" => "july",
  "08" => "august",
  "09" => "september",
  "10" => "october",
  "11" => "november",
  "12" => "december"
);

($year1, $month1, $day1) = &prepare_date ($ARGV[0]);
die "Error in date: $ARGV[0]\n" if (!defined $year1 || !defined $month1 || !defined $day1);
$startdate = $date = &Date2Julian ($year1, $month1, $day1, 0);
($year2, $month2, $day2) = &prepare_date ($ARGV[1]);
die "Error in date: $ARGV[1]\n" if (!defined $year2 || !defined $month2 || !defined $day2);
$enddate = &Date2Julian ($year2, $month2, $day2, 0);
@sep = ("", ".", "/", "\\", "-", ":", ",");
$sep_cnt = $#sep + 1;
while ($date <= $enddate)
{
  @dat = Julian2Date ($date);
  $dat[1] = "0" . $dat[1] if ($dat[1] < 10);
  $dat[2] = "0" . $dat[2] if ($dat[2] < 10);
  for ($i = 0; $i < $sep_cnt; $i++)
  {
    # YYYYMMDD
    print $dat[0] . $sep[$i] . $dat[1] . $sep[$i] . $dat[2] . "\n";
    print $dat[0] . $sep[$i] . substr ($mon{$dat[1]}, 0, 3) . $sep[$i] . $dat[2] . "\n";
    print $dat[0] . $sep[$i] . uc (substr ($mon{$dat[1]}, 0, 3)) . $sep[$i] . $dat[2] . "\n";
    print $dat[0] . $sep[$i] . ucfirst (substr ($mon{$dat[1]}, 0, 3)) . $sep[$i] . $dat[2] . "\n";
    print $dat[0] . $sep[$i] . $mon{$dat[1]} . $sep[$i] . $dat[2] . "\n";
    print $dat[0] . $sep[$i] . uc ($mon{$dat[1]}) . $sep[$i] . $dat[2] . "\n";
    print $dat[0] . $sep[$i] . ucfirst ($mon{$dat[1]}) . $sep[$i] . $dat[2] . "\n";

    # DDMMYYYY
    print $dat[2] . $sep[$i] . $dat[1] . $sep[$i] . $dat[0] . "\n";
    print $dat[2] . $sep[$i] . substr ($mon{$dat[1]}, 0, 3) . $sep[$i] . $dat[0] . "\n";
    print $dat[2] . $sep[$i] . uc (substr ($mon{$dat[1]}, 0, 3)) . $sep[$i] . $dat[0] . "\n";
    print $dat[2] . $sep[$i] . ucfirst (substr ($mon{$dat[1]}, 0, 3)) . $sep[$i] . $dat[0] . "\n";
    print $dat[2] . $sep[$i] . $mon{$dat[1]} . $sep[$i] . $dat[0] . "\n";
    print $dat[2] . $sep[$i] . uc ($mon{$dat[1]}) . $sep[$i] . $dat[0] . "\n";
    print $dat[2] . $sep[$i] . ucfirst ($mon{$dat[1]}) . $sep[$i] . $dat[0] . "\n";

    # DDMMYY
    $dd = substr ($dat[0], 2, 2);
    print $dat[2] . $sep[$i] . $dat[1] . $sep[$i] . $dd . "\n";
    print $dat[2] . $sep[$i] . substr ($mon{$dat[1]}, 0, 3) . $sep[$i] . $dd . "\n";
    print $dat[2] . $sep[$i] . uc (substr ($mon{$dat[1]}, 0, 3)) . $sep[$i] . $dd . "\n";
    print $dat[2] . $sep[$i] . ucfirst (substr ($mon{$dat[1]}, 0, 3)) . $sep[$i] . $dd . "\n";
    print $dat[2] . $sep[$i] . $mon{$dat[1]} . $sep[$i] . $dd . "\n";
    print $dat[2] . $sep[$i] . uc ($mon{$dat[1]}) . $sep[$i] . $dd . "\n";
    print $dat[2] . $sep[$i] . ucfirst ($mon{$dat[1]}) . $sep[$i] . $dd . "\n";

    # YYMMDD
    print $dd . $sep[$i] . $dat[1] . $sep[$i] . $dat[2] . "\n";
    print $dd . $sep[$i] . substr ($mon{$dat[1]}, 0, 3) . $sep[$i] . $dat[2] . "\n";
    print $dd . $sep[$i] . uc (substr ($mon{$dat[1]}, 0, 3)) . $sep[$i] . $dat[2] . "\n";
    print $dd . $sep[$i] . ucfirst (substr ($mon{$dat[1]}, 0, 3)) . $sep[$i] . $dat[2] . "\n";
    print $dd . $sep[$i] . $mon{$dat[1]} . $sep[$i] . $dat[2] . "\n";
    print $dd . $sep[$i] . uc ($mon{$dat[1]}) . $sep[$i] . $dat[2] . "\n";
    print $dd . $sep[$i] . ucfirst ($mon{$dat[1]}) . $sep[$i] . $dat[2] . "\n";
  }
  $date++;
}

exit 0;

sub usage ()
{
  print "Usage: $0 [start_date [end_date]]\n";
  print "  ex.: $0 1999/08/11\n";
  print "     : $0 1960/01/01 2002/12/31\n";
  exit 0;
}

sub prepare_date ($)
{
  my ($date_str) = @_;
  my ($year, $month, $day);

  ($year, $month, $day) = split (/\//, $date_str);
  $year =~ s/[^\d]+//g if ($year =~ /[^\d]/);
  $month =~ s/[^\d]+// if ($month =~ /[^\d]/);
  $day =~ s/[^\d]+// if ($day =~ /[^\d]/);
  $year = substr ($year, 0, 4) if (length ($year) > 4);
  $month = substr ($month, 0, 2) if (length ($month) > 2);
  $day = substr ($day, 0, 2) if (length ($day) > 2);
  $year =~ s/^0+// if ($year =~ /^0/);
  $month =~ s/^0// if ($month =~ /^0/);
  $day =~ s/^0// if ($day =~ /^0/);
  return undef if (($month < 1) || $month > 12);
  return undef if (($day < 1) || $day > 31);
  return ($year, $month, $day);
}
код функций Date2Julian и Julian2Date вынес в отдельный пакет Julian.pm
Код:
package Julian;
use strict;
use vars qw (@EXPORT @ISA $VERSION);
require Exporter;

$VERSION = "0.1";
@ISA = qw (Exporter);
@EXPORT = qw (Date2Julian Julian2Date);
#-----------------------------------------------------------------------#
#  Date2Julian: Julian Date                                             #
#      The routine is valid for any date since 4713 BC.                 #
#      Julian calendar is used up to 1582 October 4,                    #
#      Gregorian calendar is used from 1582 October 15 onwards.         #
#-----------------------------------------------------------------------#
sub Date2Julian ($$$$)
{
  my ($year, $month, $day, $hour) = @_;
  my ($A, $B, $jd);

  $A = 10000.0 * $year + 100.0 * $month + $day;
  if ($month <= 2)
  {
    $month += 12;
    $year--;
  }
  if ($A <= 15821004.1)
  {
    $B = -2 + int (($year + 4716) / 4) - 1179;
  }
  else
  {
    $B = int ($year / 400) - int ($year / 100) + int ($year / 4);
  }
  $A = 365 * $year - 679004.0;
  $jd = $A + $B + int (30.6001 * ($month + 1)) + $day + $hour / 24.0;
  return $jd + 2400000.5;
}

#---------------------------------------------------------------------------#
# Julian2Date: Finds the civil calendar date for a given value              #
#              of the Julian Date (JD).                                     #
#              Julian calendar is used up to 1582 October 4,                #
#              Gregorian calendar is used from 1582 October 15 onwards.     #
#---------------------------------------------------------------------------#
sub Julian2Date ($)
{
  my ($jd) = @_;
  my ($day, $month, $year, $hour);
  my ($B, $D, $F);
  my ($jd0, $C, $E, @dat);

  $jd0 = int ($jd + 0.5);
  if ($jd0 < 2299161.0)                 # calendar
  {
    $C = $jd0 + 1524.0;                 # -> Julian
  }
  else                                  # -> Gregorian
  {
    $B = int (($jd0 - 1867216.25) / 36524.25);
    $C = $jd0 + ($B - int ($B / 4)) +1525.0;
  }
  $D = int (($C - 122.1) / 365.25);
  $E = 365.0 * $D + int ($D / 4);
  $F = int (($C - $E) / 30.6001);
  $day = int ($C - $E + 0.5) - int (30.6001 * $F);
  $month = $F - 1 - 12 * int ($F / 14);
  $year = $D - 4715 - int ((7 + $month) / 10);
  $hour = 24.0 * ($jd + 0.5 - $jd0);
  @dat = ($year, $month, $day, $hour);
  return @dat;
}
При использовании года в формате YY (две последние цифры года) и при охвате периода более ста лет в словаре возможны повторения.
Возможно, скриптик будет полезен кому-нить.
 
Ответить с цитированием