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

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

header improvements : type of parameters and keywords, default values, spell checking + idldoc assistant (IDL online_help)

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