source: trunk/SRC/Calendar/caldat.pro @ 134

Last change on this file since 134 was 134, checked in by navarro, 18 years ago

change *.pro file properties (del eof-style, del executable, set keywords Id

  • Property svn:eol-style set to native
  • Property svn:keywords set to Id
File size: 6.3 KB
Line 
1;+
2;
3; @file_comments
4;       Return the calendar date and time given julian date.
5;       This is the inverse of the function JULDAY.
6;
7; @categories Calendar
8;
9;
10; @param JULIAN {in}{required} contains the Julian Day Number (which begins at noon) of the
11;       specified calendar date.  It should be a long integer.
12;
13; @param MONTH {out} Number of the desired month (1 = January, ..., 12 = December).
14;
15; @param DAY {out} Number of day of the month.
16;
17; @param YEAR {out} Number of the desired year.
18;
19; @param HOUR {out} Hour of the day
20;
21; @param Minute {out} Minute of the day
22;
23; @param Second {out} Second (and fractions) of the day.
24;
25;
26; @keyword NDAYSPM {default=30} for using a calendar with fixed number of days per
27;                months.
28;
29; @uses cm_4cal
30;
31;
32; @restrictions Accuracy using IEEE double precision numbers is approximately
33;       1/10000th of a second.
34;
35; @history Translated from "Numerical Recipies in C", by William H. Press,
36;       Brian P. Flannery, Saul A. Teukolsky, and William T. Vetterling.
37;       Cambridge University Press, 1988 (second printing).
38;
39;       DMS, July 1992.
40;       DMS, April 1996, Added HOUR, MINUTE and SECOND keyword
41;       AB, 7 December 1997, Generalized to handle array input.
42;
43;       Eric Guilyardi, June 1999
44;       Added key_work ndayspm for fixed number of days per months
45;
46;       AB, 3 January 2000, Make seconds output as DOUBLE in array output.
47;
48; @version $Id$
49;-
50pro CALDAT, julian, month, day, year, hour, minute, second, NDAYSPM = ndayspm
51;------------------------------------------------------------
52@cm_4cal
53;------------------------------------------------------------
54  COMPILE_OPT idl2
55
56  ON_ERROR, 2                   ; Return to caller if errors
57
58  IF n_elements(key_caltype) EQ 0 THEN key_caltype = 'greg'
59  if keyword_set(ndayspm) then key_caltype = '360d'
60  CASE key_caltype OF
61    'greg':BEGIN
62
63      nParam = N_PARAMS()
64      IF (nParam LT 1) THEN MESSAGE, 'Incorrect number of arguments.'
65
66      min_julian = -1095
67      max_julian = 1827933925
68      minn = MIN(julian, MAX = maxx)
69      IF (minn LT min_julian) OR (maxx GT max_julian) THEN MESSAGE, $
70        'Value of Julian date is out of allowed range.'
71
72      igreg = 2299161L                   ;Beginning of Gregorian calendar
73      julLong = FLOOR(julian + 0.5d)     ;Better be long
74      minJul = MIN(julLong)
75
76      IF (minJul GE igreg) THEN BEGIN ; all are Gregorian
77        jalpha = LONG(((julLong - 1867216L) - 0.25d) / 36524.25d)
78        ja = julLong + 1L + jalpha - long(0.25d * jalpha)
79      ENDIF ELSE BEGIN
80        ja = julLong
81        gregChange = WHERE(julLong ge igreg, ngreg)
82        IF (ngreg GT 0) THEN BEGIN
83          jalpha = long(((julLong[gregChange] - 1867216L) - 0.25d) / 36524.25d)
84          ja[gregChange] = julLong[gregChange] + 1L + jalpha - long(0.25d * jalpha)
85        ENDIF
86      ENDELSE
87      jalpha = -1               ; clear memory
88
89      jb = TEMPORARY(ja) + 1524L
90      jc = long(6680d + ((jb-2439870L)-122.1d0)/365.25d)
91      jd = long(365d * jc + (0.25d * jc))
92      je = long((jb - jd) / 30.6001d)
93
94      day = TEMPORARY(jb) - TEMPORARY(jd) - long(30.6001d * je)
95      month = TEMPORARY(je) - 1L
96      month = ((TEMPORARY(month) - 1L) MOD 12L) + 1L
97      year = TEMPORARY(jc) - 4715L
98      year = TEMPORARY(year) - (month GT 2)
99      year = year - (year LE 0)
100; see if we need to do hours, minutes, seconds
101      IF (nParam GT 4) THEN BEGIN
102        fraction = julian + 0.5d - TEMPORARY(julLong)
103        hour = floor(fraction * 24d)
104        fraction = TEMPORARY(fraction) - hour/24d
105        minute = floor(fraction*1440d)
106        second = (TEMPORARY(fraction) - minute/1440d) * 86400d
107      ENDIF
108
109; if julian is an array, reform all output to correct dimensions
110      IF (SIZE(julian, /N_DIMENSION) GT 0) THEN BEGIN
111        dimensions = SIZE(julian, /DIMENSION)
112        month = REFORM(month, dimensions)
113        day = REFORM(day, dimensions)
114        year = REFORM(year, dimensions)
115        IF (nParam GT 4) THEN BEGIN
116          hour = REFORM(hour, dimensions)
117          minute = REFORM(minute, dimensions)
118          second = REFORM(second, dimensions)
119        ENDIF
120      ENDIF
121
122    END
123    '360d':BEGIN
124
125      jul = long(julian)
126      f = (jul - floor(jul))
127      IF total(f NE 0.0) GT 0 THEN BEGIN ;Get hours, minutes, seconds.
128        hour = floor(f*24.)
129        f = f - hour / 24.d
130        minute = floor(f*1440)
131        second = (f - minute/1440.d0) * 86400.0d0
132      ENDIF ELSE BEGIN
133        hour = replicate(0L,  n_elements(julian))
134        minute = replicate(0L,  n_elements(julian))
135        second = replicate(0L,  n_elements(julian))
136      ENDELSE
137
138      IF keyword_set(ndayspm) THEN BEGIN
139        IF ndayspm EQ 1 THEN ndayspm = 30
140      ENDIF ELSE ndayspm = 30
141
142      ndayspm = long(ndayspm)
143      Z = floor(julian)
144      year = z/(12*ndayspm)+1
145      month = (z-(12*ndayspm)*(year-1))/ndayspm+1
146      day = z-(12*ndayspm)*(year-1)-ndayspm*(month-1)
147      WHILE total(day LT 1) GT 0 DO BEGIN
148        tochange = where(day LT 1)
149        month[tochange] = month[tochange]-1
150        day[tochange] = day[tochange]+ndayspm
151      ENDWHILE
152      WHILE total(month LT 1) GT 0 DO BEGIN
153        tochange = where(month LT 1)
154        year[tochange] = year[tochange]-1
155        month[tochange] = month[tochange]+12
156      ENDWHILE
157; year 0 does not exist...
158      neg = where(year LT 0)
159      IF neg[0] NE -1 THEN year[neg] = year[neg]-1
160    END
161    'noleap':BEGIN
162
163      jul = long(julian)
164      year = jul/365 + 1
165      day = jul MOD 365L
166;
167;
168      zero = where(day EQ 0)
169 ;
170      month = 1 + (day GT 31) + (day GT 59) + (day GT 90) + (day GT 120) $
171              + (day GT 151) + (day GT 181) + (day GT 212) + (day GT 243) $
172              + (day GT 273) + (day GT 304) + (day GT 334)
173      month = long(month)
174;
175      day = day - 31L * (day GT 31) - 28L * (day GT 59) - 31L * (day GT 90) $
176              - 30L * (day GT 120) - 31L * (day GT 151) - 30L * (day GT 181) $
177              - 31L * (day GT 212) - 31L * (day GT 243) - 30L * (day GT 273) $
178              - 31L * (day GT 304) - 30L * (day GT 334)
179;
180      IF zero[0] NE -1 THEN BEGIN
181        year[zero] = year[zero]-1
182        month[zero] = 12L
183        day[zero] = 31L
184      ENDIF
185
186    END
187    ELSE:BEGIN
188      ng = report('only 3 types of calendar are accepted: greg, 360d and noleap')
189      return
190    END
191  ENDCASE
192;
193  zero = where(year ge 600000L, cnt)
194  IF cnt NE 0 THEN year[zero] = year[zero]-654321L
195;
196  return
197
198END
Note: See TracBrowser for help on using the repository browser.