|
Познавший АНТИЧАТ
Регистрация: 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 (две последние цифры года) и при охвате периода более ста лет в словаре возможны повторения.
Возможно, скриптик будет полезен кому-нить.
|