Changeset 9 for trunk/ToBeReviewed/CALENDRIER/julday.pro
- Timestamp:
- 04/26/06 16:29:38 (18 years ago)
- File:
-
- 1 copied
Legend:
- Unmodified
- Added
- Removed
-
trunk/ToBeReviewed/CALENDRIER/julday.pro
r7 r9 1 1 ; $Id$ 2 2 ; 3 ; Copyright (c) 1988- 1998, Research Systems, Inc. All rights reserved.3 ; Copyright (c) 1988-2003, Research Systems, Inc. All rights reserved. 4 4 ; Unauthorized reproduction prohibited. 5 5 6 function JULDAY, MONTH, DAY, YEAR, Hour, Minute, Second, NDAYSPM = ndayspm, _extra=ex7 6 ;+ 8 7 ; NAME: … … 13 12 ; This is the inverse of the library function CALDAT. 14 13 ; See also caldat, the inverse of this function. 14 ; 15 15 ; CATEGORY: 16 16 ; Misc. 17 17 ; 18 18 ; CALLING SEQUENCE: 19 ; Result = JULDAY( Month, Day, Year)19 ; Result = JULDAY([[[[Month, Day, Year], Hour], Minute], Second]) 20 20 ; 21 21 ; INPUTS: … … 24 24 ; DAY: Number of day of the month. 25 25 ; 26 ; YEAR: Number of the desired year. 26 ; YEAR: Number of the desired year.Year parameters must be valid 27 ; values from the civil calendar. Years B.C.E. are represented 28 ; as negative integers. Years in the common era are represented 29 ; as positive integers. In particular, note that there is no 30 ; year 0 in the civil calendar. 1 B.C.E. (-1) is followed by 31 ; 1 C.E. (1). 27 32 ; 28 33 ; HOUR: Number of the hour of the day. … … 30 35 ; MINUTE: Number of the minute of the hour. 31 36 ; 32 ; SECOND: 37 ; SECOND: Number of the second of the minute. 38 ; 39 ; Note: Month, Day, Year, Hour, Minute, and Second can all be arrays. 40 ; The Result will have the same dimensions as the smallest array, or 41 ; will be a scalar if all arguments are scalars. 33 42 ; 34 43 ; OPTIONAL INPUT PARAMETERS: … … 37 46 ; KEYWORD PARAMETERS: 38 47 ; 39 ; NDAYSPM: developpe par eric, ca veut dire: nombre de jours par mois! 40 ; par defaut c''est 30, sinon le specifier en donnant 41 ; une valeur a ndayspm 42 ; pour passer a un calendrier avec un nombre de jours constant par 43 ; mois. Utilise en particulier ds julday et caldat 48 ; NDAYSPM: for using a calendar with fixed number of days per 49 ; months. defaut value of NDAYSPM=30 44 50 ; 45 51 ; OUTPUTS: 46 ; JULDAY returns the Julian Day Number (which begins at noon) of the 47 ; specified calendar date. If the time of day (Hr, Min, Sec), is 0,48 ; the result will be a long integer, otherwise the result is a52 ; JULDAY returns the Julian Day Number (which begins at noon) of the 53 ; specified calendar date. If Hour, Minute, and Second are not specified, 54 ; then the result will be a long integer, otherwise the result is a 49 55 ; double precision floating point number. 50 56 ; 51 ; COMMON BLOCKS: 52 ; None. 57 ; COMMON BLOCKS: cm_4cal 53 58 ; 54 59 ; SIDE EFFECTS: … … 57 62 ; RESTRICTIONS: 58 63 ; Accuracy using IEEE double precision numbers is approximately 59 ; 1/10000th of a second. 64 ; 1/10000th of a second, with higher accuracy for smaller (earlier) 65 ; Julian dates. 60 66 ; 61 67 ; MODIFICATION HISTORY: … … 69 75 ; Eric Guilyardi, June 1999 70 76 ; Added key_work ndayspm for fixed number of days per months 77 ; + change to accept year 0 78 ; 79 ; Sebastien Masson, Aug. 2003 80 ; fix bug for negative and large values of month values 81 ; eg. julday(349,1,1970) 82 ; 83 ; CT, April 2000, Now accepts vectors or scalars. 71 84 ;- 72 85 ; 73 ON_ERROR, 2 ; Return to caller if errors 74 75 MONTHS = ['JAN','FEB','MAR','APR','MAY','JUN','JUL','AUG', $ 76 'SEP','OCT','NOV','DEC'] 77 78 IF NOT keyword_set(ndayspm) THEN BEGIN 86 function JULDAY, MONTH, DAY, YEAR, Hour, Minute, Second, NDAYSPM = ndayspm 87 ;------------------------------------------------------------ 88 @cm_4cal 89 ;------------------------------------------------------------ 90 91 COMPILE_OPT idl2 92 93 ON_ERROR, 2 ; Return to caller if errors 94 95 IF n_elements(key_caltype) EQ 0 THEN key_caltype = 'greg' 96 if keyword_set(ndayspm) then key_caltype = '360d' 97 ; 98 CASE key_caltype OF 99 'greg':BEGIN 100 79 101 80 102 ; Gregorian Calander was adopted on Oct. 15, 1582 81 GREG = 15L + 31L * (10L + 12L * 1582L) 103 ; skipping from Oct. 4, 1582 to Oct. 15, 1582 104 GREG = 2299171L ; incorrect Julian day for Oct. 25, 1582 82 105 83 106 ; Process the input, if all are missing, use todays date. 84 107 NP = n_params() 85 if NP eq 0 then begin 86 DATE = systime() 87 L_MONTH = long(where(strupcase(strmid(DATE, 4, 3)) eq MONTHS)) 88 L_MONTH = L_MONTH[0] + 1 ; Scalarize it... 89 L_DAY = long(strmid(DATE, 8, 2)) 90 L_YEAR = long(strmid(DATE, 20, 4)) 91 endif else if np ge 3 then begin 92 L_MONTH = LONG(MONTH) 93 L_DAY = LONG(DAY) 94 L_YEAR=LONG(YEAR) 95 ; 96 ;*************************************************** 97 ; Change test to allow year 0 for climatological data 98 ;******************************************************** 99 ; if (L_YEAR eq 0) then message, 'There is no year zero.' 100 endif else message, 'Wrong number of parameters.' 101 ; 102 ;*************************************************** 103 ; Change test to allow year 0 for climatological data 104 ;******************************************************** 105 ; if (L_YEAR lt 0) then L_YEAR = L_YEAR + 1 106 if (L_YEAR le 0) then L_YEAR = L_YEAR + 1 107 if (L_MONTH gt 2) then begin 108 JY = L_YEAR 109 JM = L_MONTH + 1 110 endif else begin 111 JY = L_YEAR - 1 112 JM = L_MONTH + 13 113 endelse 114 115 JUL = floor(365.25 * JY) + floor(30.6001 * JM) + L_DAY + 1720995 108 IF (np EQ 0) THEN RETURN, SYSTIME(/JULIAN) 109 IF (np LT 3) THEN MESSAGE, 'Incorrect number of arguments.' 110 111 ; Find the dimensions of the Result: 112 ; 1. Find all of the input arguments that are arrays (ignore scalars) 113 ; 2. Out of the arrays, find the smallest number of elements 114 ; 3. Find the dimensions of the smallest array 115 116 ; Step 1: find all array arguments 117 nDims = [SIZE(month, /N_DIMENSIONS), SIZE(day, /N_DIMENSIONS), $ 118 SIZE(year, /N_DIMENSIONS), SIZE(hour, /N_DIMENSIONS), $ 119 SIZE(minute, /N_DIMENSIONS), SIZE(second, /N_DIMENSIONS)] 120 arrays = WHERE(nDims GE 1) 121 122 nJulian = 1L ; assume everything is a scalar 123 IF (arrays[0] GE 0) THEN BEGIN 124 ; Step 2: find the smallest number of elements 125 nElement = [N_ELEMENTS(month), N_ELEMENTS(day), $ 126 N_ELEMENTS(year), N_ELEMENTS(hour), $ 127 N_ELEMENTS(minute), N_ELEMENTS(second)] 128 nJulian = MIN(nElement[arrays], whichVar) 129 ; step 3: find dimensions of the smallest array 130 CASE arrays[whichVar] OF 131 0: julianDims = SIZE(month, /DIMENSIONS) 132 1: julianDims = SIZE(day, /DIMENSIONS) 133 2: julianDims = SIZE(year, /DIMENSIONS) 134 3: julianDims = SIZE(hour, /DIMENSIONS) 135 4: julianDims = SIZE(minute, /DIMENSIONS) 136 5: julianDims = SIZE(second, /DIMENSIONS) 137 ENDCASE 138 ENDIF 139 140 d_Second = 0d ; defaults 141 d_Minute = 0d 142 d_Hour = 0d 143 ; convert all Arguments to appropriate array size & type 144 SWITCH np OF ; use switch so we fall thru all arguments... 145 6: d_Second = (SIZE(second, /N_DIMENSIONS) GT 0) ? $ 146 second[0:nJulian-1] : second 147 5: d_Minute = (SIZE(minute, /N_DIMENSIONS) GT 0) ? $ 148 minute[0:nJulian-1] : minute 149 4: d_Hour = (SIZE(hour, /N_DIMENSIONS) GT 0) ? $ 150 hour[0:nJulian-1] : hour 151 3: BEGIN ; convert m,d,y to type LONG 152 L_MONTH = (SIZE(month, /N_DIMENSIONS) GT 0) ? $ 153 LONG(month[0:nJulian-1]) : LONG(month) 154 L_DAY = (SIZE(day, /N_DIMENSIONS) GT 0) ? $ 155 LONG(day[0:nJulian-1]) : LONG(day) 156 L_YEAR = (SIZE(year, /N_DIMENSIONS) GT 0) ? $ 157 LONG(year[0:nJulian-1]) : LONG(year) 158 END 159 ENDSWITCH 160 161 162 min_calendar = -4716 163 max_calendar = 5000000 164 minn = MIN(l_year, MAX = maxx) 165 IF (minn LT min_calendar) OR (maxx GT max_calendar) THEN MESSAGE, $ 166 'Value of Julian date is out of allowed range.' 167 ; change to accept year 0 168 ; if (MAX(L_YEAR eq 0) NE 0) then message, $ 169 ; 'There is no year zero in the civil calendar.' 170 ; 171 ; by seb Aug 2003 172 tochange = where(L_MONTH LT 0) 173 IF tochange[0] NE -1 THEN BEGIN 174 L_YEAR[tochange] = L_YEAR[tochange]+L_MONTH[tochange]/12-1 175 L_MONTH[tochange] = 12 + L_MONTH[tochange] MOD 12 176 ENDIF 177 tochange = where(L_MONTH GT 12) 178 IF tochange[0] NE -1 THEN BEGIN 179 L_YEAR[tochange] = L_YEAR[tochange]+L_MONTH[tochange]/12 180 L_MONTH[tochange] = L_MONTH[tochange] MOD 12 181 ENDIF 182 ; by seb Aug 2003 - end 183 ; 184 ; 185 bc = (L_YEAR LT 0) 186 L_YEAR = TEMPORARY(L_YEAR) + TEMPORARY(bc) 187 inJanFeb = (L_MONTH LE 2) 188 JY = L_YEAR - inJanFeb 189 JM = L_MONTH + (1b + 12b*TEMPORARY(inJanFeb)) 190 191 192 JUL = floor(365.25d * JY) + floor(30.6001d*TEMPORARY(JM)) + L_DAY + 1720995L 193 194 116 195 ; Test whether to change to Gregorian Calandar. 117 if ((L_DAY + 31L * (L_MONTH + 12L * L_YEAR)) ge GREG) then begin 118 JA = long(0.01 * JY) 119 JUL = JUL + 2 - JA + long(0.25 * JA) 120 endif 121 122 if n_elements(Hour) + n_elements(Minute) + n_elements(Second) eq 0 then $ 123 return, JUL 124 if n_elements(Hour) eq 0 then Hour = 0 125 if n_elements(Minute) eq 0 then Minute = 0 126 if n_elements(Second) eq 0 then Second = 0 127 128 return, JUL + (Hour / 24.0d0 - .5d0) + (Minute/1440.0d0) + (Second / 86400.0d0) 129 130 ENDIF ELSE BEGIN 196 IF (MIN(JUL) GE GREG) THEN BEGIN ; change all dates 197 JA = long(0.01d * TEMPORARY(JY)) 198 JUL = TEMPORARY(JUL) + 2L - JA + long(0.25d * JA) 199 ENDIF ELSE BEGIN 200 gregChange = WHERE(JUL ge GREG, ngreg) 201 IF (ngreg GT 0) THEN BEGIN 202 JA = long(0.01d * JY[gregChange]) 203 JUL[gregChange] = JUL[gregChange] + 2L - JA + long(0.25d * JA) 204 ENDIF 205 ENDELSE 206 207 208 ; hour,minute,second? 209 IF (np GT 3) THEN BEGIN ; yes, compute the fractional Julian date 210 ; Add a small offset so we get the hours, minutes, & seconds back correctly 211 ; if we convert the Julian dates back. This offset is proportional to the 212 ; Julian date, so small dates (a long, long time ago) will be "more" accurate. 213 eps = (MACHAR(/DOUBLE)).eps 214 eps = eps*ABS(jul) > eps 215 ; For Hours, divide by 24, then subtract 0.5, in case we have unsigned ints. 216 jul = TEMPORARY(JUL) + ( (TEMPORARY(d_Hour)/24d - 0.5d) + $ 217 TEMPORARY(d_Minute)/1440d + TEMPORARY(d_Second)/86400d + eps ) 218 ENDIF 219 220 ; check to see if we need to reform vector to array of correct dimensions 221 IF (N_ELEMENTS(julianDims) GT 1) THEN $ 222 JUL = REFORM(TEMPORARY(JUL), julianDims) 223 224 RETURN, jul 225 226 END 227 '360d':BEGIN 131 228 ; 132 229 ; Fixed number of days per month (default=30) : 133 230 ; 134 IF ndayspm EQ 1 THEN ndayspm = 30 231 IF keyword_set(ndayspm) THEN BEGIN 232 IF ndayspm EQ 1 THEN ndayspm = 30 233 ENDIF ELSE ndayspm = 30 135 234 136 235 L_MONTH = LONG(MONTH) 137 236 L_DAY = LONG(DAY) 138 L_YEAR=LONG(YEAR) 139 140 JUL = ((L_YEAR-1)*12. + (L_MONTH-1))* ndayspm + L_DAY 237 L_YEAR = LONG(YEAR) 238 239 neg = where(L_YEAR LT 0) 240 IF neg[0] NE -1 THEN L_YEAR[neg] = L_YEAR[neg]+1 241 242 JUL = ((L_YEAR-1)*12 + (L_MONTH-1))* ndayspm + L_DAY 141 243 if n_elements(Hour) + n_elements(Minute) + n_elements(Second) eq 0 then $ 142 return, JUL244 return, JUL 143 245 if n_elements(Hour) eq 0 then Hour = 0 144 246 if n_elements(Minute) eq 0 then Minute = 0 145 247 if n_elements(Second) eq 0 then Second = 0 146 248 147 return, JUL + (Hour / 24.0d0) + (Minute/1440.0d0) + (Second / 86400.0d0) 148 149 ENDELSE 150 end 249 IF Hour+Minute+Second EQ 0 THEN return, JUL ELSE $ 250 return, JUL + (Hour / 24.0d0) + (Minute/1440.0d0) + (Second / 86400.0d0) 251 252 END 253 'noleap':BEGIN 254 END 255 ELSE:return, report('only 3 types of calendar are accepted: greg, 360d and noleap') 256 ENDCASE 257 258 END
Note: See TracChangeset
for help on using the changeset viewer.