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

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

typo

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