gordan@maccs.McMaster.CA (gordan) (10/09/88)
In article <7618@rpp386.Dallas.TX.US> jfh@rpp386.Dallas.TX.US (The Beach Bum) writes: -In article <44100014@hcx2> danr@hcx2.SSD.HARRIS.COM writes: ->> Does anyone have a routine to change back and forth between ->>seconds from 19xx to a Year, Month, Day sort of Date? Well, astronomers tend to worry about this sort of thing a lot. The September (or May?) 1984 issue of Sky and Telescope magazine devoted some space to this problem, publishing two BASIC (yuck) programs that convert from year/month/day to Julian date, and vice versa. The Julian date is simply the number of days since January 1, 4713 BC. The two functions are astonishingly short, using some sort of floating point trickery. They seemed to work when I tested them. Conversion to C is left as an exercise for the reader. Unless speed is critical, this sort of approach is suitable for all manner of calendar-related problems. For instance if you need to know what the date will be tomorrow, you need only call the first function to find the Julian date, add 1, and call the second function to convert back to year, month, and day. Absolutely no bother worrying about how many days any month has or whether a year is a leap year. This should help deal with the problem you're working on (just multiply days by 86400 to get seconds, unless you have to worry about leap seconds). An added bonus is that the day of the week of any date can be determined as well. Just find the Julian date, divide by 7, and find the remainder. (If you use the routines below, I think a remainder of 0 indicates a Monday, 1 a Tuesday, and so on up to 6 being a Sunday. It's a bit tricky since Julian days are considered to start at noon rather than midnight.) -- Gordan Palameta uunet!ai.toronto.edu!utgpu!maccs!gordan ***** Date to Julian Day number ********* Simplified from original in Sky and Telescope (no fractional days, Gregorian calendar only). May not work for negative years if your version of Basic truncates (-10/6) to -1 rather than -2 (which is also what Fortran and most pocket calculators do). Note SGN is the sign function (+1 or -1). See September 1984 Sky and Telescope page 255. The following are given as test cases: DATE JULIAN DAY Mar 1 200 1794168 Feb 29 1984 2445760 Jan 1 2000 2451545 Mar 21 3000 2816867 Note astronomers should interpret the above as: Mar 1.5 200 = JD 1794168.0, and so on. 800 REM CALENDAR --> JD 801 REM 802 REM NOTE: JD THAT 803 REM IS CALCULATED IS THE JULIAN 804 REM DAY THAT BEGINS AT NOON 805 REM GREENWICH MEAN TIME OF THE 806 REM GIVEN DATE (Y,M,D). 809 REM 810 INPUT "Y,M,D ";Y,M,D 825 J=-INT(7*(INT((M+9)/12)+Y)/4) 835 S=SGN(M-9): A=ABS(M-9) 840 J1=INT(Y+S*INT(A/7)) 845 J1=-INT((INT(J1/100)+1)*3/4) 850 J=J+INT(275*M/9)+D+J1 855 J=J+1721029+367*Y 870 PRINT "J.D.: ";J 875 END 900 REM JD --> CALENDAR 901 REM 902 REM NOTE: CALENDAR DATE 903 REM CALCULATED CORRESPONDS TO THE 904 REM DATE ON WHICH THE JULIAN DAY 905 REM BEGINS AT NOON GREENWICH MEAN 906 REM TIME. 909 REM 910 INPUT "J.D. ";J 945 A1=INT((J/36524.25)-51.12264) 950 A=J+1+A1-INT(A1/4) 955 B=A+1524 960 C=INT((B/365.25)-0.3343) 965 D=INT(365.25*C) 970 E=INT((B-D)/30.61) 975 D=B-D-INT(30.61*E) 980 M=E-1: Y=C-4716 985 IF E>13.5 THEN M=M-12 990 IF M<2.5 THEN Y=Y+1 995 PRINT "DATE: ";Y;M;D 997 END
dal@midgard.mn.org (Dale Schumacher) (10/12/88)
In article <1483@maccs.McMaster.CA> gordan@maccs.UUCP () writes: |In article <7618@rpp386.Dallas.TX.US> jfh@rpp386.Dallas.TX.US (The Beach Bum) writes: |-In article <44100014@hcx2> danr@hcx2.SSD.HARRIS.COM writes: |->> Does anyone have a routine to change back and forth between |->>seconds from 19xx to a Year, Month, Day sort of Date? | |Well, astronomers tend to worry about this sort of thing a lot. | |The September (or May?) 1984 issue of Sky and Telescope magazine devoted |some space to this problem, publishing two BASIC (yuck) programs that |convert from year/month/day to Julian date, and vice versa. The Julian |date is simply the number of days since January 1, 4713 BC. | |The two functions are astonishingly short, using some sort of floating |point trickery. They seemed to work when I tested them. Conversion to |C is left as an exercise for the reader. I don't think floating point is required. I know that it isn't for the formula that I have. I haven't compared the to closely enough (nor do I want to) to determine if they are identical. In any case, the following source code from dLibs (which is public domain) calculated julian date very nicely, and it's supposed to be accurate to +/- 4 million years! long julian_date(time) register struct tm *time; /* * Number of days since the base date of the Julian calendar. */ { register long c, y, m, d; y = time->tm_year + 1900; /* year - 1900 */ m = time->tm_mon + 1; /* month, 0..11 */ d = time->tm_mday; /* day, 1..31 */ if(m > 2) m -= 3L; else { m += 9L; y -= 1L; } c = y / 100L; y %= 100L; return( ((146097L * c) >> 2) + ((1461L * y) >> 2) + (((153L * m) + 2) / 5) + d + 172119L ); } PS. If you define your days of the week as: char *day[] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" }; the day-of-week is: day[(julian_date(t) + 1L) % 7L]; (ie. the julian day 0 is a Monday.)
gordan@maccs.McMaster.CA (gordan) (10/20/88)
In article <483@midgard.mn.org> dal@syntel.UUCP (Dale Schumacher) writes: -In article <1483@maccs.McMaster.CA> gordan@maccs.UUCP () writes: -| -|The two functions are astonishingly short, using some sort of floating -|point trickery. They seemed to work when I tested them. Conversion to -|C is left as an exercise for the reader. - -I don't think floating point is required. I know that it isn't for the -formula that I have. I haven't compared the to closely enough (nor do I [code omitted] Yes, but the code you supply only does D/M/Y --> JD, not vice versa. Believe it or not, there's a one-line Fortran statement that does D/M/Y --> JD, which was also published in Sky & Telescope in 1984. Actually it was the "vice versa" routine (JD --> D/M/Y) that did the floating point.