home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / perl_ste.zip / Time / JulianDay.pm < prev    next >
Text File  |  1996-07-25  |  5KB  |  189 lines

  1. package Time::JulianDay;
  2.  
  3. require 5.000;
  4.  
  5. use Carp;
  6. use Time::Timezone;
  7.  
  8. @ISA = qw(Exporter);
  9. @EXPORT = qw(julian_day inverse_julian_day day_of_week 
  10.     jd_secondsgm jd_secondslocal 
  11.     jd_timegm jd_timelocal 
  12.     gm_julian_day local_julian_day 
  13.     );
  14. @EXPORT_OK = qw($brit_jd);
  15.  
  16. use strict;
  17. use integer;
  18.  
  19. # constants
  20. use vars qw($brit_jd $jd_1970_1_1 $VERSION);
  21.  
  22. $VERSION = 96.032702;
  23.  
  24. # calculate the julian day, given $year, $month and $day
  25. sub julian_day
  26. {
  27.     my($year, $month, $day) = @_;
  28.     my($tmp);
  29.     my($secs);
  30.  
  31.     use Carp;
  32. #    confess() unless defined $day;
  33.  
  34.     $tmp = $day - 32075
  35.       + 1461 * ( $year + 4800 - ( 14 - $month ) / 12 )/4
  36.       + 367 * ( $month - 2 + ( ( 14 - $month ) / 12 ) * 12 ) / 12
  37.       - 3 * ( ( $year + 4900 - ( 14 - $month ) / 12 ) / 100 ) / 4
  38.       ;
  39.  
  40.     return($tmp);
  41.  
  42. }
  43.  
  44. sub gm_julian_day
  45. {
  46.     my($secs) = @_;
  47.     my($sec, $min, $hour, $mon, $year, $day, $month);
  48.     ($sec, $min, $hour, $day, $mon, $year) = gmtime($secs);
  49.     $month = $mon + 1;
  50.     $year += 100 if $year < 70;
  51.     $year += 1900 if $year < 171;
  52.     return julian_day($year, $month, $day)
  53. }
  54.  
  55. sub local_julian_day
  56. {
  57.     my($secs) = @_;
  58.     my($sec, $min, $hour, $mon, $year, $day, $month);
  59.     ($sec, $min, $hour, $day, $mon, $year) = localtime($secs);
  60.     $month = $mon + 1;
  61.     $year += 100 if $year < 70;
  62.     $year += 1900 if $year < 171;
  63.     return julian_day($year, $month, $day)
  64. }
  65.  
  66. sub day_of_week
  67. {
  68.     my ($jd) = @_;
  69.         return (($jd + 1) % 7);       # calculate weekday (0=Sun,6=Sat)
  70. }
  71.  
  72.  
  73. # The following defines the first day that the Gregorian calendar was used
  74. # in the British Empire (Sep 14, 1752).  The previous day was Sep 2, 1752
  75. # by the Julian Calendar.  The year began at March 25th before this date.
  76.  
  77. $brit_jd = 2361222;
  78.  
  79. # Usage:  ($year,$month,$day) = &inverse_julian_day($julian_day)
  80. sub inverse_julian_day
  81. {
  82.         my($jd) = @_;
  83.         my($jdate_tmp);
  84.         my($m,$d,$y);
  85.  
  86.         carp("warning: julian date $jd pre-dates British use of Gregorian calendar\n")
  87.                 if ($jd < $brit_jd);
  88.  
  89.         $jdate_tmp = $jd - 1721119;
  90.         $y = (4 * $jdate_tmp - 1)/146097;
  91.         $jdate_tmp = 4 * $jdate_tmp - 1 - 146097 * $y;
  92.         $d = $jdate_tmp/4;
  93.         $jdate_tmp = (4 * $d + 3)/1461;
  94.         $d = 4 * $d + 3 - 1461 * $jdate_tmp;
  95.         $d = ($d + 4)/4;
  96.         $m = (5 * $d - 3)/153;
  97.         $d = 5 * $d - 3 - 153 * $m;
  98.         $d = ($d + 5) / 5;
  99.         $y = 100 * $y + $jdate_tmp;
  100.         if($m < 10) {
  101.                 $m += 3;
  102.         } else {
  103.                 $m -= 9;
  104.                 ++$y;
  105.         }
  106.         return ($y, $m, $d);
  107. }
  108.  
  109. $jd_1970_1_1 = 2440588;
  110.  
  111. sub jd_secondsgm
  112. {
  113.     my($jd, $hr, $min, $sec) = @_;
  114.  
  115.     return (($jd - $jd_1970_1_1) * 86400 + $hr * 3600 + $min * 60 + $sec);
  116. }
  117.  
  118. sub jd_secondslocal
  119. {
  120.     my($jd, $hr, $min, $sec) = @_;
  121.     my $jds = jd_secondsgm($jd, $hr, $min, $sec);
  122.     return $jds - tz_local_offset($jds);
  123. }
  124.  
  125. # this uses a 0-11 month to correctly reverse localtime()
  126. sub jd_timelocal
  127. {
  128.     my ($sec,$min,$hours,$mday,$mon,$year) = @_;
  129.     $year += 100 if $year < 70;
  130.     $year += 1900 if $year < 1900;
  131.     my $jd = julian_day($year, $mon+1, $mday);
  132.     my $jds = jd_secondsgm($jd, $hours, $min, $sec);
  133.     return $jds - tz_local_offset($jds);
  134. }
  135.  
  136. # this uses a 0-11 month to correctly reverse gmtime()
  137. sub jd_timegm
  138. {
  139.     my ($sec,$min,$hours,$mday,$mon,$year) = @_;
  140.     $year += 100 if $year < 70;
  141.     $year += 1900 if $year < 1900;
  142.     my $jd = julian_day($year, $mon+1, $mday);
  143.     return jd_secondsgm($jd, $hours, $min, $sec);
  144. }
  145.  
  146. 1;
  147.  
  148. __DATA__
  149.  
  150. =head1 NAME
  151.  
  152. Time::JulianDay -- Julian calendar manipulations
  153.  
  154. =head1 SYNOPSIS
  155.  
  156.     use Time::JulianDay
  157.  
  158.     $jd = julian_day($year, $month_1_to_12, $day)
  159.     $jd = local_julian_day($seconds_since_1970);
  160.     $jd = gm_julian_day($seconds_since_1970);
  161.     ($year, $month_1_to_12, $day) = inverse_julian_day($jd)
  162.     $dow = day_of_week($jd) 
  163.  
  164.     print (Sun,Mon,Tue,Wed,Thu,Fri,Sat)[$dow];
  165.  
  166.     $seconds_since_jan_1_1970 = jd_secondslocal($jd, $hour, $min, $sec)
  167.     $seconds_since_jan_1_1970 = jd_secondsgm($jd, $hour, $min, $sec)
  168.     $seconds_since_jan_1_1970 = jd_timelocal($sec,$min,$hours,$mday,$month_0_to_11,$year)
  169.     $seconds_since_jan_1_1970 = jd_timegm($sec,$min,$hours,$mday,$month_0_to_11,$year)
  170.  
  171. =head1 DESCRIPTION
  172.  
  173. JulianDay is a package that manipulates dates as number of days since 
  174. some time a long time ago.  It's easy to add and subtract time
  175. using julian days...  
  176.  
  177. The day_of_week returned by day_of_week() is 0 for Sunday, and 6 for
  178. Saturday and everything else is in between.
  179.  
  180. =head1 GENESIS
  181.  
  182. Written by David Muir Sharnoff <muir@idiom.com> with help from
  183. previous work by 
  184. Kurt Jaeger aka PI <zrzr0111@helpdesk.rus.uni-stuttgart.de>
  185.      based on postings from: Ian Miller <ian_m@cix.compulink.co.uk>;
  186. Gary Puckering <garyp%cognos.uucp@uunet.uu.net>
  187.     based on Collected Algorithms of the ACM ?;
  188. and the unknown-to-me author of Time::Local.
  189.