Article 8986 of comp.lang.perl: Xref: feenix.metronet.com comp.lang.perl:8986 Path: feenix.metronet.com!news.ecn.bgu.edu!usenet.ins.cwru.edu!howland.reston.ans.net!xlink.net!rz.uni-karlsruhe.de!news.uni-stuttgart.de!zrzr0111 From: zrzr0111@helpdesk.rus.uni-stuttgart.de (Kurt Jaeger aka PI) Newsgroups: comp.lang.perl Subject: Re: Julian Date? Date: 17 Dec 1993 20:05:59 GMT Organization: Comp.Center (RUS), U of Stuttgart, FRG Lines: 291 Message-ID: <2et3f7$1reu@info2.rus.uni-stuttgart.de> References: NNTP-Posting-Host: helpdesk.rus.uni-stuttgart.de In article , David Lopata wrote: > I assume converting the standard date line to a julian number >(am I phrasing this right?) and then subtracting the two numbers would >be the most efficient way. > > Does anyone know how to acccomplish this in Perl? Yes, give the source following below a try. #!/bin/sh # This is a shell archive (produced by shar 3.49) # To extract the files from this archive, save it to a file, remove # everything above the "!/bin/sh" line above, and type "sh file_name". # # made 12/17/1993 20:05 UTC by zrzr0111@helpdesk # Source directory /helpdesk/z/zr/0111/zrzr/src # # existing files will NOT be overwritten unless -c is specified # # This shar contains: # length mode name # ------ ---------- ------------------------------------------ # 1468 -rw-r--r-- day-of-year/README # 1463 -rw-r--r-- day-of-year/day-of-year.c # 3213 -rwxr-xr-x day-of-year/day-of-year.perl # # ============= day-of-year/README ============== if test ! -d 'day-of-year'; then echo 'x - creating directory day-of-year' mkdir 'day-of-year' fi if test -f 'day-of-year/README' -a X"$1" != X"-c"; then echo 'x - skipping day-of-year/README (File already exists)' else echo 'x - extracting day-of-year/README (Text)' sed 's/^X//' << 'SHAR_EOF' > 'day-of-year/README' && XFrom: ism@metagen.uucp (Ian Miller) Subject: Re: Determining the Day of the Week Message-ID: <184@babbage.metagen.uucp> Date: 25 May 93 18:01:23 GMT Organization: Meta_Generics Ltd, Cambridge, UK X The simplest technique is probably to convert to a Julian Day number and then take the result mod7. This has the advantage that you can do a lot of other things with Julian Day number as well. The best algorithm I know of was published as a letter from Henry F Fliegel and Thomas C van Flandern in the October 1968 (vol 11 #10) issue of the Communications of the ACM. X Julian Day Number = day - 32075 + 1461 * (year + 4800 - (14 - month)/12)/4 + X 367 * (month - 2 + (14 - month)/12*12)/12 - X 3 * ((year + 4900 - (14 - month)/12)/100)/4 X This is valid for all dates in the Gregorian Calendar up to 28 Feb 4000. (I have modified this algorithm slightly from the original to avoid dividing negative numbers. The original only worked in FORTRAN. The modified version should work in any language.) X They also quote the following reverse algorithm:- X temp1 = julian_date + 68569 temp2 = 4*temp1/146097 temp1 = temp1 - (146097 * temp2 + 3) / 4 year = 4000 * (temp1 + 1) / 1461001 temp1 = temp1 - 1461 * year/4 + 31 month = 80 * temp1 / 2447 day = temp1 - 247 * month / 80 temp1 = month / 11 month = month + 2 - 12 * temp1 year = 100 * (temp2 - 49) + year + temp1 X They do work. Don't ask me how. X X -- Ian Miller Any replies to: ian_m@cix.compulink.co.uk X SHAR_EOF chmod 0644 day-of-year/README || echo 'restore of day-of-year/README failed' Wc_c="`wc -c < 'day-of-year/README'`" test 1468 -eq "$Wc_c" || echo 'day-of-year/README: original size 1468, current size' "$Wc_c" fi # ============= day-of-year/day-of-year.c ============== if test -f 'day-of-year/day-of-year.c' -a X"$1" != X"-c"; then echo 'x - skipping day-of-year/day-of-year.c (File already exists)' else echo 'x - extracting day-of-year/day-of-year.c (Text)' sed 's/^X//' << 'SHAR_EOF' > 'day-of-year/day-of-year.c' && #include X int julian_day(int, int, int); void inverse_julian_day(int, int*,int*,int*); X main() { X int offset; /* offset into the julian day */ X int y,m,d; /* invers jul day */ X int i,j,k; /* loop for year/month/day */ X int erg; X int old; X X offset=julian_day(1988,1,1); X /* printf("off: %d\n",offset); */ X X for(i=1988; i<=1998; i++) { X for(j=1; j<=12; j++) { X erg=julian_day(i,j,1); X inverse_julian_day(erg,&y,&m,&d); X printf("Y: %4d ergabs: %6d ergrel: %5d Y: %4d M: %2d D: %2d\n", X i,erg,erg-offset,y,m,d); X } X } X } X /* X this works, indeed ! X from a given date, gives a continous day-number relative to some X date in the past, correcting leap-years etc. */ int julian_day(int year, int month, int day) { X X int tmp; X X tmp = day - 32075 + 1461 * (year + 4800 - (14 - month)/12)/4 + X 367 * (month - 2 + (14 - month)/12*12)/12 - X 3 * ((year + 4900 - (14 - month)/12)/100)/4; X X return(tmp); X } X void inverse_julian_day(int jul_day, int *year, int *month, int *day) { X int temp1,temp2; X X temp1 = jul_day + 68569; X temp2 = 4*temp1/146097; X temp1 = temp1 - (146097 * temp2 + 3) / 4; X *year = 4000 * (temp1 + 1) / 1461001; X temp1 = temp1 - 1461 * (*year)/4 + 31; X *month= 80 * temp1 / 2447; X *day = temp1 - 247 * (*month) / 80; X temp1 = (*month) / 11; X *month= (*month) + 2 - 12 * temp1; X *year = 100 * (temp2 - 49) + (*year) + temp1; X } X SHAR_EOF chmod 0644 day-of-year/day-of-year.c || echo 'restore of day-of-year/day-of-year.c failed' Wc_c="`wc -c < 'day-of-year/day-of-year.c'`" test 1463 -eq "$Wc_c" || echo 'day-of-year/day-of-year.c: original size 1463, current size' "$Wc_c" fi # ============= day-of-year/day-of-year.perl ============== if test -f 'day-of-year/day-of-year.perl' -a X"$1" != X"-c"; then echo 'x - skipping day-of-year/day-of-year.perl (File already exists)' else echo 'x - extracting day-of-year/day-of-year.perl (Text)' sed 's/^X//' << 'SHAR_EOF' > 'day-of-year/day-of-year.perl' && #!/usr/bin/perl X $offset=&julian_day("1988","1","1"); X for $j (1988..1998) { X for $i (1..12) { X $erg=&julian_day($j,$i,"1"); X ($y,$m,$d) = &inverse_julian_day($erg); X printf "Y: %4d ergabs: %5d ergrel: %5d Y: %4d M: %2d D: %3d\n", X $j,$erg,$erg-$offset,$y,$m,$d; X } } X Xexit 0; X # calculate the julian day, given $year, $month and $day sub julian_day { X local($year, $month, $day) = @_; X local($tmp); X X $tmp = $day - 32075 X + int( X 1461*($year + 4800 - int( X ( X 14 - $month X )/12 X ) X )/4 X ) X + int( X 367*($month -2 + int( X (14 - $month X )/12 X )*12 X )/12 X ) X - int( X 3*( X ( X $year + 4900 - ( X 14 - $month X )/12 X )/100 X )/4 X ) X ; X X return($tmp); X } X sub inverse_julian_day { X local($julian_day) = @_; X local($year,$month,$day); X local($temp1,$temp2); X X $temp1 = $julian_day + 68569; X $temp2 = int(4*$temp1/146097); X $temp1 = $temp1 - int((146097 * $temp2 + 3) / 4); X $year = int(4000 * ($temp1 + 1) / 1461001); X $temp1 = $temp1 - int(1461 * $year/4) + 31; X $month = int(80 * $temp1 / 2447); X $day = $temp1 - int(247 * $month / 80); X $temp1 = int($month / 11); X $month = $month + 2 - 12 * $temp1; X $year = 100 * ($temp2 - 49) + $year + $temp1; X X return($year, $month, $day); X } X # From: ian_m@cix.compulink.co.uk (Ian Miller) # Subject: Re: Determining the Day of the Week # Message-ID: <184@babbage.metagen.uucp> # Date: 25 May 93 18:01:23 GMT # Organization: Meta_Generics Ltd, Cambridge, UK # # The simplest technique is probably to convert to a Julian Day number and # then take the result mod7. This has the advantage that you can # do a lot of other things with Julian Day number as well. The best # algorithm I know of was published as a letter from Henry F Fliegel and # Thomas C van Flandern in the October 1968 (vol 11 #10) issue of the # Communications of the ACM. # # Julian Day Number = day - 32075 + 1461 * (year + 4800 - (14 - month)/12)/4 + # 367 * (month - 2 + (14 - month)/12*12)/12 - # 3 * ((year + 4900 - (14 - month)/12)/100)/4 # # This is valid for all dates in the Gregorian Calendar up to 28 Feb 4000. # (I have modified this algorithm slightly from the original to avoid dividing # negative numbers. The original only worked in FORTRAN. The modified version # should work in any language.) # # They also quote the following reverse algorithm:- # # temp1 = julian_date + 68569 # temp2 = 4*temp1/146097 # temp1 = temp1 - (146097 * temp2 + 3) / 4 # year = 4000 * (temp1 + 1) / 1461001 # temp1 = temp1 - 1461 * year/4 + 31 # month = 80 * temp1 / 2447 # day = temp1 - 247 * month / 80 # temp1 = month / 11 # month = month + 2 - 12 * temp1 # year = 100 * (temp2 - 49) + year + temp1 # # They do work. Don't ask me how. # X SHAR_EOF chmod 0755 day-of-year/day-of-year.perl || echo 'restore of day-of-year/day-of-year.perl failed' Wc_c="`wc -c < 'day-of-year/day-of-year.perl'`" test 3213 -eq "$Wc_c" || echo 'day-of-year/day-of-year.perl: original size 3213, current size' "$Wc_c" fi exit 0 -- PI at the User Help Desk Comp.Center U of Stuttgart, FRG 27 years to go ! EMail: pi@rus.uni-stuttgart.de Phone: +49 711 685-4828 (aka Kurt Jaeger)