source: trunk/SRC/Calendar/caldat.pro

Last change on this file was 495, checked in by pinsard, 10 years ago

fix thanks to coding rules; typo; dupe empty lines; trailing blanks

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