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

Last change on this file since 205 was 205, checked in by smasson, 17 years ago

improve the use of high frequency calendar

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