Below is the code to convert, among other things, Unix epoch
seconds to year, month ... minute, second. What i have not tested is
if it is any better in terms of accuracy than using built-in
localtime(), or various epoch based date/time modules.
#!/usr/local/bin/perl -w
use strict;
# About:
# -----
# Author: Parv, parv underscore at yahoo dot com
# Modified: dec 20 2000
#
# Currently this program does the below stated conversion, but can be
# (easily) extended to do other conversions.
#
# Unix date/time in seconds is converted to year, month, day, hour,
# minute, second.
#
# Credits:
# -------
# This program's date conversion algorithm is based on an
# article about inter-date conversions (shown via JavaScript);
# author of the article is John Walker, founder of AutoCad.
# Article copies are available at many places, two of which 're...
#
# http://www.fourmilab.ch/documents/calendar/
# http://www.michaelmccafferty.com/mmmdate.htm
#
# ...The article recommends/referrers to...
#
# 1. Astronomical algorithms,
# Mjean Meeus; 1991; ISBN: 0-943396-35-2
#
# 2. Explanatory supplement to the astronomical almanac,
# p. Kenneth Seidelmann (ed.); 1992; ISBN: 0-935702-68-7
#
# adjust unix epoch in julian day by 0.5 so that day starts on
# midnight instead of noon
#
use constant Unix_Epoc_Julian => 2440587.5 +0.5;
# other constants
use constant Avg_JulianCal_Yr => 365.25;
use constant Avg_GregorianCal_Yr => 365.2425;
convert_show_datetime(@ARGV);
sub convert_show_datetime
{
for (@ARGV)
{
# check if an argument is a digit(s)
#
unless (m#\d+#)
{
print "\n# $_ is not a number, skipping...\n";
next;
}
# convert given seconds into (fractional) julian days
#
my $t = unixSec2julianDay($_);
my $t_2 = int($t);
my $diff = $t - $t_2;
# get date & time...
my ($year, $month, $day) = julianDay2date($t_2, $diff);
my ($hour, $min, $sec) = julianDay2time($diff);
print <<DATETIME;
for $_ ...
...date (year month day) is: $year $month $day
...time (hour minute sec) is: $hour $min $sec
DATETIME
}
}
sub unixSec2julianDay
{
# convert unix seconds time to fractional julian day
my ($sec) = @_;
return 0 if not_digit($sec);
return Unix_Epoc_Julian + ($sec /60 /60 /24);
}
sub julianDay2time
{
# return fractional julian day as list of hour, minute, second
#
my ($diff) = @_;
return ('00', '00', '00') if not_digit($diff);
# convert difference of julian days to seconds
#
my $sec = $diff *60 *60 *24;
# zero-pad upto 2 characters before giving hour, minute,
# second (in that order)
#
return ( sprintf("%02s", int($sec /60 /60)),
sprintf("%02s", int(($sec /60) %60)),
sprintf("%02s", int($sec %60))
);
}
sub julianDay2date
{
# return fractional julian day as list of year, month, day
#
my ($days, $diff) = @_;
if (not_digit($days) || not_digit($diff))
{ return ('0000', '00', '00'); }
my ($x, $y, $m, $d);
# calculate year, month, day
#
if ($days < 2299161) { $x = $days; }
else
{
$y = int( ($days -1867216.25) / Avg_GregorianCal_Yr /100 );
$x = $days + $y - int($y /4) +1;
}
$y = int( ($x +1524 -122.1) / Avg_JulianCal_Yr );
$m = int( ($x +1524 - int($y * Avg_JulianCal_Yr)) /30.6001 );
$d = int( $x +1524 + $diff - int($y * Avg_JulianCal_Yr) - int($m *30.
+6001) );
$m = ($m < 14) ? ($m -1) : ($m -13);
$y = ($m > 2) ? ($y -4716) : ($y -4715);
# zero-pad year, month, day before returning
#
return ( sprintf("%04s", $y),
sprintf("%02s", $m),
sprintf("%02s", $d)
);
}
sub not_digit
{
my ($d) = @_;
return 1 if !((defined $d) || ($d =~ m/\d+/));
return 0;
}
Originally posted as a Categorized Answer. |