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

Last change on this file since 237 was 231, checked in by pinsard, 17 years ago

improvements/corrections of some *.pro headers

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