source: trunk/SRC/ToBeReviewed/CALENDRIER/caldat.pro @ 80

Last change on this file since 80 was 69, checked in by smasson, 18 years ago

debug + new xxx

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