Ignore:
Timestamp:
04/26/06 16:29:38 (18 years ago)
Author:
pinsard
Message:

upgrade of CALENDRIER/Calendar according to cerbere.lodyc.jussieu.fr:/usr/home/smasson/SAXO_RD/ : files

File:
1 copied

Legend:

Unmodified
Added
Removed
  • trunk/ToBeReviewed/CALENDRIER/julday.pro

    r7 r9  
    11; $Id$ 
    22; 
    3 ; Copyright (c) 1988-1998, Research Systems, Inc.  All rights reserved. 
     3; Copyright (c) 1988-2003, Research Systems, Inc.  All rights reserved. 
    44;       Unauthorized reproduction prohibited. 
    55 
    6 function JULDAY, MONTH, DAY, YEAR, Hour, Minute, Second, NDAYSPM = ndayspm, _extra=ex 
    76;+ 
    87; NAME: 
     
    1312;       This is the inverse of the library function CALDAT. 
    1413;       See also caldat, the inverse of this function. 
     14; 
    1515; CATEGORY: 
    1616;       Misc. 
    1717; 
    1818; CALLING SEQUENCE: 
    19 ;       Result = JULDAY(Month, Day, Year) 
     19;       Result = JULDAY([[[[Month, Day, Year], Hour], Minute], Second]) 
    2020; 
    2121; INPUTS: 
     
    2424;       DAY:    Number of day of the month. 
    2525; 
    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). 
    2732; 
    2833;       HOUR:   Number of the hour of the day. 
     
    3035;       MINUTE: Number of the minute of the hour. 
    3136; 
    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. 
    3342; 
    3443; OPTIONAL INPUT PARAMETERS: 
     
    3746; KEYWORD PARAMETERS: 
    3847; 
    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 
    4450; 
    4551; 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 a  
     52;       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 
    4955;       double precision floating point number. 
    5056; 
    51 ; COMMON BLOCKS: 
    52 ;       None. 
     57; COMMON BLOCKS: cm_4cal 
    5358; 
    5459; SIDE EFFECTS: 
     
    5762; RESTRICTIONS: 
    5863;       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. 
    6066; 
    6167; MODIFICATION HISTORY: 
     
    6975;       Eric Guilyardi, June 1999 
    7076;       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. 
    7184;- 
    7285; 
    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  
     86function 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 
    79101 
    80102; 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 
    82105 
    83106; Process the input, if all are missing, use todays date. 
    84107      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 
    116195; 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 
    131228; 
    132229; Fixed number of days per month (default=30) : 
    133230; 
    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 
    135234 
    136235      L_MONTH = LONG(MONTH) 
    137236      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  
    141243      if n_elements(Hour) + n_elements(Minute) + n_elements(Second) eq 0 then $ 
    142        return, JUL 
     244        return, JUL 
    143245      if n_elements(Hour) eq 0 then Hour = 0 
    144246      if n_elements(Minute) eq 0 then Minute = 0 
    145247      if n_elements(Second) eq 0 then Second = 0 
    146248       
    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 
     258END 
Note: See TracChangeset for help on using the changeset viewer.