1 |
MODULE calendar |
MODULE calendar |
2 |
!$Header: /home/ioipsl/CVSROOT/IOIPSL/src/calendar.f90,v 2.0 2004/04/05 14:47:47 adm Exp $ |
|
3 |
!- |
! From IOIPSL/src/calendar.f90, version 2.0 2004/04/05 14:47:47 |
4 |
!--------------------------------------------------------------------- |
|
5 |
!- This is the calendar which going to be used to do all |
! This is the calendar used to do all calculations on time. Three |
6 |
!- calculations on time. Three types of calendars are possible : |
! types of calendars are possible: |
7 |
!- - gregorian : The normal calendar. The time origin for the |
|
8 |
!- julian day in this case is 24 Nov -4713 |
! - Gregorian: |
9 |
!- - nolap : A 365 day year without leap years. |
! The normal calendar. The time origin for the julian day in this |
10 |
!- The origin for the julian days is in this case 1 Jan 0 |
! case is 24 Nov -4713. |
11 |
!- - xxxd : Year of xxx days with month of equal length. |
|
12 |
!- The origin for the julian days is then also 1 Jan 0 |
! - No leap: |
13 |
!- As one can see it is difficult to go from one calendar to the other. |
! A 365 day year without leap years. The origin for the julian days |
14 |
!- All operations involving julian days will be wrong. |
! is in this case 1 Jan 0. |
15 |
!- This calendar will lock as soon as possible |
|
16 |
!- the length of the year and forbid any further modification. |
! - xxxd: |
17 |
!- |
! Year of xxx days with months of equal length. The origin for the |
18 |
!- For the non leap-year calendar the method is still brute force. |
! julian days is then also 1 Jan 0. |
19 |
!- We need to find an Integer series which takes care of the length |
|
20 |
!- of the various month. (Jan) |
! As one can see it is difficult to go from one calendar to the |
21 |
!- |
! other. All operations involving julian days will be wrong. This |
22 |
!- un_jour : one day in seconds |
! calendar will lock as soon as possible the length of the year and |
23 |
!- un_an : one year in days |
! forbid any further modification. |
24 |
!--------------------------------------------------------------------- |
|
25 |
USE stringop, ONLY : strlowercase |
! For the non leap-year calendar the method is still brute force. |
26 |
USE errioipsl, ONLY : histerr |
! We need to find an integer series which takes care of the length |
27 |
!- |
! of the various month. (Jan) |
28 |
|
|
29 |
|
USE strlowercase_m, ONLY: strlowercase |
30 |
|
USE errioipsl, ONLY: histerr |
31 |
|
|
32 |
|
IMPLICIT NONE |
33 |
|
|
34 |
PRIVATE |
PRIVATE |
35 |
PUBLIC :: ymds2ju,ju2ymds,tlen2itau,isittime,ioconf_calendar, & |
PUBLIC ymds2ju, ju2ymds, isittime, ioconf_calendar, itau2date, lock_unan, & |
36 |
& ioget_calendar,itau2date,ioget_timestamp, & |
calendar_used, un_an, un_jour |
37 |
& ioconf_startdate,itau2ymds,time_diff,time_add |
|
38 |
!- |
REAL, PARAMETER:: un_jour = 86400. ! one day in seconds |
39 |
INTERFACE ioget_calendar |
LOGICAL:: lock_startdate = .FALSE. |
40 |
MODULE PROCEDURE & |
|
41 |
& ioget_calendar_real1,ioget_calendar_real2,ioget_calendar_str |
CHARACTER(LEN=30):: time_stamp = 'XXXXXXXXXXXXXXXX' |
42 |
END INTERFACE |
|
43 |
!- |
! Description of calendar |
44 |
INTERFACE ioconf_startdate |
|
45 |
MODULE PROCEDURE & |
CHARACTER(LEN=20):: calendar_used = "gregorian" |
46 |
& ioconf_startdate_simple,ioconf_startdate_internal, & |
LOGICAL:: lock_unan = .FALSE. |
47 |
& ioconf_startdate_ymds |
REAL:: un_an = 365.2425 ! one year in days |
48 |
END INTERFACE |
INTEGER:: mon_len(12) = (/31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/) |
49 |
!- |
|
50 |
REAL,PARAMETER :: un_jour = 86400.0 |
CHARACTER(LEN=3), PARAMETER:: cal(12) = (/'JAN', 'FEB', 'MAR', 'APR', & |
51 |
LOGICAL,SAVE :: lock_startdate = .FALSE. |
'MAY', 'JUN', 'JUL', 'AUG', 'SEP', 'OCT', 'NOV', 'DEC'/) |
52 |
!- |
|
53 |
CHARACTER(LEN=30),SAVE :: time_stamp='XXXXXXXXXXXXXXXX' |
REAL, SAVE:: start_day, start_sec |
|
!- |
|
|
!- Description of calendar |
|
|
!- |
|
|
CHARACTER(LEN=20),SAVE :: calendar_used="gregorian" |
|
|
LOGICAL,SAVE :: lock_unan = .FALSE. |
|
|
REAL,SAVE :: un_an = 365.2425 |
|
|
INTEGER,SAVE :: mon_len(12)=(/31,28,31,30,31,30,31,31,30,31,30,31/) |
|
|
!- |
|
|
!- |
|
|
!- |
|
|
CHARACTER(LEN=3),PARAMETER :: & |
|
|
& cal(12) = (/'JAN','FEB','MAR','APR','MAY','JUN', & |
|
|
& 'JUL','AUG','SEP','OCT','NOV','DEC'/) |
|
|
!- |
|
|
REAL,SAVE :: start_day,start_sec |
|
54 |
|
|
55 |
CONTAINS |
CONTAINS |
56 |
|
|
57 |
SUBROUTINE ymds2ju (year,month,day,sec,julian) |
SUBROUTINE ymds2ju (year, month, day, sec, julian) |
58 |
|
|
59 |
IMPLICIT NONE |
INTEGER, INTENT(IN):: year, month, day |
60 |
|
REAL, INTENT(IN):: sec |
61 |
|
REAL, INTENT(OUT):: julian |
62 |
|
|
63 |
INTEGER,INTENT(IN) :: year,month,day |
INTEGER:: julian_day |
64 |
REAL,INTENT(IN) :: sec |
REAL:: julian_sec |
65 |
|
|
66 |
REAL,INTENT(OUT) :: julian |
!-------------------------------------------------------------------- |
67 |
|
|
68 |
INTEGER :: julian_day |
CALL ymds2ju_internal(year, month, day, sec, julian_day, julian_sec) |
69 |
REAL :: julian_sec |
julian = julian_day + julian_sec / un_jour |
|
!--------------------------------------------------------------------- |
|
|
CALL ymds2ju_internal (year,month,day,sec,julian_day,julian_sec) |
|
70 |
|
|
|
julian = julian_day+julian_sec / un_jour |
|
|
!--------------------- |
|
71 |
END SUBROUTINE ymds2ju |
END SUBROUTINE ymds2ju |
72 |
|
|
73 |
!=== |
!=== |
74 |
|
|
75 |
SUBROUTINE ymds2ju_internal (year,month,day,sec,julian_day,julian_sec) |
SUBROUTINE ymds2ju_internal (year, month, day, sec, julian_day, julian_sec) |
76 |
!--------------------------------------------------------------------- |
|
77 |
!- Converts year, month, day and seconds into a julian day |
! Converts year, month, day and seconds into a julian day |
78 |
|
|
79 |
!- In 1968 in a letter to the editor of Communications of the ACM |
! In 1968 in a letter to the editor of Communications of the ACM |
80 |
!- (CACM, volume 11, number 10, October 1968, p.657) Henry F. Fliegel |
! (CACM, volume 11, number 10, October 1968, p.657) Henry F. Fliegel |
81 |
!- and Thomas C. Van Flandern presented such an algorithm. |
! and Thomas C. Van Flandern presented such an algorithm. |
82 |
|
|
83 |
!- See also : http://www.magnet.ch/serendipity/hermetic/cal_stud/jdn.htm |
! See also: http://www.magnet.ch/serendipity/hermetic/cal_stud/jdn.htm |
84 |
|
|
85 |
!- In the case of the Gregorian calendar we have chosen to use |
! In the case of the Gregorian calendar we have chosen to use |
86 |
!- the Lilian day numbers. This is the day counter which starts |
! the Lilian day numbers. This is the day counter which starts |
87 |
!- on the 15th October 1582. |
! on the 15th October 1582. |
88 |
!- This is the day at which Pope Gregory XIII introduced the |
! This is the day at which Pope Gregory XIII introduced the |
89 |
!- Gregorian calendar. |
! Gregorian calendar. |
90 |
!- Compared to the true Julian calendar, which starts some |
! Compared to the true Julian calendar, which starts some |
91 |
!- 7980 years ago, the Lilian days are smaler and are dealt with |
! 7980 years ago, the Lilian days are smaler and are dealt with |
92 |
!- easily on 32 bit machines. With the true Julian days you can only |
! easily on 32 bit machines. With the true Julian days you can only |
93 |
!- the fraction of the day in the real part to a precision of |
! the fraction of the day in the real part to a precision of |
94 |
!- a 1/4 of a day with 32 bits. |
! a 1/4 of a day with 32 bits. |
|
!--------------------------------------------------------------------- |
|
|
IMPLICIT NONE |
|
95 |
|
|
96 |
INTEGER,INTENT(IN) :: year,month,day |
INTEGER, INTENT(IN):: year, month, day |
97 |
REAL,INTENT(IN) :: sec |
REAL, INTENT(IN):: sec |
98 |
|
|
99 |
INTEGER,INTENT(OUT) :: julian_day |
INTEGER, INTENT(OUT):: julian_day |
100 |
REAL,INTENT(OUT) :: julian_sec |
REAL, INTENT(OUT):: julian_sec |
101 |
|
|
102 |
INTEGER :: jd,m,y,d,ml |
INTEGER:: jd, m, y, d, ml |
103 |
!--------------------------------------------------------------------- |
!-------------------------------------------------------------------- |
104 |
lock_unan = .TRUE. |
lock_unan = .TRUE. |
105 |
|
|
106 |
m = month |
m = month |
107 |
y = year |
y = year |
108 |
d = day |
d = day |
109 |
|
|
110 |
!- We deduce the calendar from the length of the year as it |
! We deduce the calendar from the length of the year as it |
111 |
!- is faster than an INDEX on the calendar variable. |
! is faster than an INDEX on the calendar variable. |
112 |
|
|
113 |
!- Gregorian |
! Gregorian |
114 |
IF ( (un_an > 365.0).AND.(un_an < 366.0) ) THEN |
IF ( (un_an > 365.0).AND.(un_an < 366.0) ) THEN |
115 |
jd = (1461*(y+4800+INT(( m-14 )/12)))/4 & |
jd = (1461*(y+4800+INT(( m-14 )/12)))/4 & |
116 |
& +(367*(m-2-12*(INT(( m-14 )/12))))/12 & |
& +(367*(m-2-12*(INT(( m-14 )/12))))/12 & |
117 |
& -(3*((y+4900+INT((m-14)/12))/100))/4 & |
& -(3*((y+4900+INT((m-14)/12))/100))/4 & |
118 |
& +d-32075 |
& +d-32075 |
119 |
jd = jd-2299160 |
jd = jd-2299160 |
120 |
!- No leap or All leap |
! No leap or All leap |
121 |
ELSE IF (ABS(un_an-365.0) <= EPSILON(un_an) .OR. & |
ELSE IF (ABS(un_an-365.0) <= EPSILON(un_an) .OR. & |
122 |
& ABS(un_an-366.0) <= EPSILON(un_an)) THEN |
& ABS(un_an-366.0) <= EPSILON(un_an)) THEN |
123 |
ml = SUM(mon_len(1:m-1)) |
ml = SUM(mon_len(1:m-1)) |
124 |
jd = y*INT(un_an)+ml+(d-1) |
jd = y*INT(un_an)+ml+(d-1) |
125 |
!- Calendar with regular month |
! Calendar with regular month |
126 |
ELSE |
ELSE |
127 |
ml = INT(un_an)/12 |
ml = INT(un_an)/12 |
128 |
jd = y*INT(un_an)+(m-1)*ml+(d-1) |
jd = y*INT(un_an)+(m-1)*ml+(d-1) |
130 |
|
|
131 |
julian_day = jd |
julian_day = jd |
132 |
julian_sec = sec |
julian_sec = sec |
133 |
!------------------------------ |
|
134 |
END SUBROUTINE ymds2ju_internal |
END SUBROUTINE ymds2ju_internal |
135 |
!- |
|
136 |
!=== |
!=== |
137 |
!- |
|
138 |
SUBROUTINE ju2ymds (julian,year,month,day,sec) |
SUBROUTINE ju2ymds (julian, year, month, day, sec) |
139 |
!--------------------------------------------------------------------- |
|
140 |
IMPLICIT NONE |
REAL, INTENT(IN):: julian |
141 |
|
|
142 |
REAL,INTENT(IN) :: julian |
INTEGER, INTENT(OUT):: year, month, day |
143 |
|
REAL, INTENT(OUT):: sec |
144 |
INTEGER,INTENT(OUT) :: year,month,day |
|
145 |
REAL,INTENT(OUT) :: sec |
INTEGER:: julian_day |
146 |
|
REAL:: julian_sec |
147 |
INTEGER :: julian_day |
!-------------------------------------------------------------------- |
|
REAL :: julian_sec |
|
|
!--------------------------------------------------------------------- |
|
148 |
julian_day = INT(julian) |
julian_day = INT(julian) |
149 |
julian_sec = (julian-julian_day)*un_jour |
julian_sec = (julian-julian_day)*un_jour |
150 |
|
|
151 |
CALL ju2ymds_internal(julian_day,julian_sec,year,month,day,sec) |
CALL ju2ymds_internal(julian_day, julian_sec, year, month, day, sec) |
152 |
!--------------------- |
|
153 |
END SUBROUTINE ju2ymds |
END SUBROUTINE ju2ymds |
154 |
!- |
|
155 |
!=== |
!=== |
156 |
!- |
|
157 |
SUBROUTINE ju2ymds_internal (julian_day,julian_sec,year,month,day,sec) |
SUBROUTINE ju2ymds_internal (julian_day, julian_sec, year, month, day, sec) |
158 |
!--------------------------------------------------------------------- |
|
159 |
!- This subroutine computes from the julian day the year, |
! This subroutine computes from the julian day the year, |
160 |
!- month, day and seconds |
! month, day and seconds |
161 |
|
|
162 |
!- In 1968 in a letter to the editor of Communications of the ACM |
! In 1968 in a letter to the editor of Communications of the ACM |
163 |
!- (CACM, volume 11, number 10, October 1968, p.657) Henry F. Fliegel |
! (CACM, volume 11, number 10, October 1968, p.657) Henry F. Fliegel |
164 |
!- and Thomas C. Van Flandern presented such an algorithm. |
! and Thomas C. Van Flandern presented such an algorithm. |
165 |
|
|
166 |
!- See also : http://www.magnet.ch/serendipity/hermetic/cal_stud/jdn.htm |
! See also: http://www.magnet.ch/serendipity/hermetic/cal_stud/jdn.htm |
167 |
|
|
168 |
!- In the case of the Gregorian calendar we have chosen to use |
! In the case of the Gregorian calendar we have chosen to use |
169 |
!- the Lilian day numbers. This is the day counter which starts |
! the Lilian day numbers. This is the day counter which starts |
170 |
!- on the 15th October 1582. This is the day at which Pope |
! on the 15th October 1582. This is the day at which Pope |
171 |
!- Gregory XIII introduced the Gregorian calendar. |
! Gregory XIII introduced the Gregorian calendar. |
172 |
!- Compared to the true Julian calendar, which starts some 7980 |
! Compared to the true Julian calendar, which starts some 7980 |
173 |
!- years ago, the Lilian days are smaler and are dealt with easily |
! years ago, the Lilian days are smaler and are dealt with easily |
174 |
!- on 32 bit machines. With the true Julian days you can only the |
! on 32 bit machines. With the true Julian days you can only the |
175 |
!- fraction of the day in the real part to a precision of a 1/4 of |
! fraction of the day in the real part to a precision of a 1/4 of |
176 |
!- a day with 32 bits. |
! a day with 32 bits. |
177 |
!--------------------------------------------------------------------- |
|
178 |
IMPLICIT NONE |
INTEGER, INTENT(IN):: julian_day |
179 |
|
REAL, INTENT(IN):: julian_sec |
180 |
INTEGER,INTENT(IN) :: julian_day |
|
181 |
REAL,INTENT(IN) :: julian_sec |
INTEGER, INTENT(OUT):: year, month, day |
182 |
|
REAL, INTENT(OUT):: sec |
183 |
INTEGER,INTENT(OUT) :: year,month,day |
|
184 |
REAL,INTENT(OUT) :: sec |
INTEGER:: l, n, i, jd, j, d, m, y, ml |
185 |
|
INTEGER:: add_day |
186 |
INTEGER :: l,n,i,jd,j,d,m,y,ml |
!-------------------------------------------------------------------- |
|
INTEGER :: add_day |
|
|
!--------------------------------------------------------------------- |
|
187 |
lock_unan = .TRUE. |
lock_unan = .TRUE. |
188 |
|
|
189 |
jd = julian_day |
jd = julian_day |
194 |
jd = jd+add_day |
jd = jd+add_day |
195 |
ENDIF |
ENDIF |
196 |
|
|
197 |
!- Gregorian |
! Gregorian |
198 |
IF ( (un_an > 365.0).AND.(un_an < 366.0) ) THEN |
IF ( (un_an > 365.0).AND.(un_an < 366.0) ) THEN |
199 |
jd = jd+2299160 |
jd = jd+2299160 |
200 |
|
|
208 |
l = j/11 |
l = j/11 |
209 |
m = j+2-(12*l) |
m = j+2-(12*l) |
210 |
y = 100*(n-49)+i+l |
y = 100*(n-49)+i+l |
211 |
!- No leap or All leap |
! No leap or All leap |
212 |
ELSE IF (ABS(un_an-365.0) <= EPSILON(un_an) .OR. & |
ELSE IF (ABS(un_an-365.0) <= EPSILON(un_an) .OR. & |
213 |
& ABS(un_an-366.0) <= EPSILON(un_an) ) THEN |
& ABS(un_an-366.0) <= EPSILON(un_an) ) THEN |
214 |
y = jd/INT(un_an) |
y = jd/INT(un_an) |
220 |
m = m+1 |
m = m+1 |
221 |
ENDDO |
ENDDO |
222 |
d = l-ml+1 |
d = l-ml+1 |
223 |
!- others |
! others |
224 |
ELSE |
ELSE |
225 |
ml = INT(un_an)/12 |
ml = INT(un_an)/12 |
226 |
y = jd/INT(un_an) |
y = jd/INT(un_an) |
232 |
day = d |
day = d |
233 |
month = m |
month = m |
234 |
year = y |
year = y |
235 |
!------------------------------ |
|
236 |
END SUBROUTINE ju2ymds_internal |
END SUBROUTINE ju2ymds_internal |
237 |
!- |
|
|
!=== |
|
|
!- |
|
|
SUBROUTINE tlen2itau (input_str,dt,date,itau) |
|
|
!--------------------------------------------------------------------- |
|
|
!- This subroutine transforms a sting containing a time length |
|
|
!- into a number of time steps. |
|
|
!- To do this operation the date (in julian days is needed as the |
|
|
!- length of the month varies. |
|
|
!- The following convention is used : |
|
|
!- n : n time steps |
|
|
!- nS : n seconds is transformed into itaus |
|
|
!- nH : n hours |
|
|
!- nD : n days |
|
|
!- nM : n month |
|
|
!- nY : n years |
|
|
!- Combinations are also possible |
|
|
!- nYmD : nyears plus m days ! |
|
|
!--------------------------------------------------------------------- |
|
|
IMPLICIT NONE |
|
|
|
|
|
CHARACTER(LEN=*),INTENT(IN) :: input_str |
|
|
REAL,INTENT(IN) :: dt,date |
|
|
|
|
|
INTEGER,INTENT(OUT) :: itau |
|
|
|
|
|
INTEGER :: y_pos,m_pos,d_pos,h_pos,s_pos |
|
|
INTEGER :: read_time |
|
|
CHARACTER(LEN=13) :: fmt |
|
|
CHARACTER(LEN=80) :: tmp_str |
|
|
|
|
|
INTEGER :: year,month,day |
|
|
REAL :: sec,date_new,dd,ss |
|
|
!--------------------------------------------------------------------- |
|
|
itau = 0 |
|
|
CALL ju2ymds (date,year,month,day,sec) |
|
|
|
|
|
y_pos = MAX(INDEX(input_str,'y'),INDEX(input_str,'Y')) |
|
|
m_pos = MAX(INDEX(input_str,'m'),INDEX(input_str,'M')) |
|
|
d_pos = MAX(INDEX(input_str,'d'),INDEX(input_str,'D')) |
|
|
h_pos = MAX(INDEX(input_str,'h'),INDEX(input_str,'H')) |
|
|
s_pos = MAX(INDEX(input_str,'s'),INDEX(input_str,'S')) |
|
|
|
|
|
IF (MAX(y_pos,m_pos,d_pos,s_pos) > 0) THEN |
|
|
tmp_str = input_str |
|
|
DO WHILE ( MAX(y_pos,m_pos,d_pos,s_pos) > 0) |
|
|
!---- WRITE(*,*) tmp_str |
|
|
!---- WRITE(*,*) y_pos,m_pos,d_pos,s_pos |
|
|
IF (y_pos > 0) THEN |
|
|
WRITE(fmt,'("(I",I10.10,")")') y_pos-1 |
|
|
READ(tmp_str(1:y_pos-1),fmt) read_time |
|
|
CALL ymds2ju (year+read_time,month,day,sec,date_new) |
|
|
dd = date_new-date |
|
|
ss = INT(dd)*un_jour+dd-INT(dd) |
|
|
itau = itau+NINT(ss/dt) |
|
|
tmp_str = tmp_str(y_pos+1:LEN_TRIM(tmp_str)) |
|
|
ELSE IF (m_pos > 0) THEN |
|
|
WRITE(fmt,'("(I",I10.10,")")') m_pos-1 |
|
|
READ(tmp_str(1:m_pos-1),fmt) read_time |
|
|
CALL ymds2ju (year,month+read_time,day,sec,date_new) |
|
|
dd = date_new-date |
|
|
ss = INT(dd)*un_jour+ dd-INT(dd) |
|
|
itau = itau+NINT(ss/dt) |
|
|
tmp_str = tmp_str(m_pos+1:LEN_TRIM(tmp_str)) |
|
|
ELSE IF (d_pos > 0) THEN |
|
|
WRITE(fmt,'("(I",I10.10,")")') d_pos-1 |
|
|
READ(tmp_str(1:d_pos-1),fmt) read_time |
|
|
itau = itau+NINT(read_time*un_jour/dt) |
|
|
tmp_str = tmp_str(d_pos+1:LEN_TRIM(tmp_str)) |
|
|
ELSE IF (h_pos > 0) THEN |
|
|
WRITE(fmt,'("(I",I10.10,")")') h_pos-1 |
|
|
READ(tmp_str(1:h_pos-1),fmt) read_time |
|
|
itau = itau+NINT(read_time*60.*60./dt) |
|
|
tmp_str = tmp_str(d_pos+1:LEN_TRIM(tmp_str)) |
|
|
ELSE IF (s_pos > 0) THEN |
|
|
WRITE(fmt,'("(I",I10.10,")")') s_pos-1 |
|
|
READ(tmp_str(1:s_pos-1),fmt) read_time |
|
|
itau = itau+NINT(read_time/dt) |
|
|
tmp_str = tmp_str(s_pos+1:LEN_TRIM(tmp_str)) |
|
|
ENDIF |
|
|
|
|
|
y_pos = MAX(INDEX(tmp_str,'y'),INDEX(tmp_str,'Y')) |
|
|
m_pos = MAX(INDEX(tmp_str,'m'),INDEX(tmp_str,'M')) |
|
|
d_pos = MAX(INDEX(tmp_str,'d'),INDEX(tmp_str,'D')) |
|
|
h_pos = MAX(INDEX(tmp_str,'h'),INDEX(tmp_str,'H')) |
|
|
s_pos = MAX(INDEX(tmp_str,'s'),INDEX(tmp_str,'S')) |
|
|
ENDDO |
|
|
ELSE |
|
|
WRITE(fmt,'("(I",I10.10,")")') LEN_TRIM(input_str) |
|
|
READ(input_str(1:LEN_TRIM(input_str)),fmt) itau |
|
|
ENDIF |
|
|
!----------------------- |
|
|
END SUBROUTINE tlen2itau |
|
|
!- |
|
238 |
!=== |
!=== |
239 |
!- |
|
240 |
REAL FUNCTION itau2date (itau,date0,deltat) |
REAL FUNCTION itau2date (itau, date0, deltat) |
241 |
!--------------------------------------------------------------------- |
|
242 |
!- This function transforms itau into a date. The date whith which |
! This function transforms itau into a date. The date whith which |
243 |
!- the time axis is going to be labeled |
! the time axis is going to be labeled |
244 |
|
|
245 |
!- INPUT |
! INPUT |
246 |
!- itau : current time step |
! itau: current time step |
247 |
!- date0 : Date at which itau was equal to 0 |
! date0: Date at which itau was equal to 0 |
248 |
!- deltat : time step between itau s |
! deltat: time step between itau s |
249 |
|
|
250 |
!- OUTPUT |
! OUTPUT |
251 |
!- itau2date : Date for the given itau |
! itau2date: Date for the given itau |
252 |
!--------------------------------------------------------------------- |
|
253 |
IMPLICIT NONE |
INTEGER:: itau |
254 |
|
REAL:: date0, deltat |
255 |
INTEGER :: itau |
!-------------------------------------------------------------------- |
|
REAL :: date0,deltat |
|
|
!--------------------------------------------------------------------- |
|
256 |
itau2date = REAL(itau)*deltat/un_jour+date0 |
itau2date = REAL(itau)*deltat/un_jour+date0 |
257 |
!--------------------- |
|
258 |
END FUNCTION itau2date |
END FUNCTION itau2date |
259 |
!- |
|
|
!=== |
|
|
!- |
|
|
SUBROUTINE itau2ymds (itau,deltat,year,month,date,sec) |
|
|
!--------------------------------------------------------------------- |
|
|
!- This subroutine transforms itau into a date. The date whith which |
|
|
!- the time axis is going to be labeled |
|
|
|
|
|
!- INPUT |
|
|
!- itau : current time step |
|
|
!- deltat : time step between itau s |
|
|
|
|
|
!- OUTPUT |
|
|
!- year : year |
|
|
!- month : month |
|
|
!- date : date |
|
|
!- sec : seconds since midnight |
|
|
!--------------------------------------------------------------------- |
|
|
IMPLICIT NONE |
|
|
|
|
|
INTEGER,INTENT(IN) :: itau |
|
|
REAL,INTENT(IN) :: deltat |
|
|
|
|
|
INTEGER,INTENT(OUT) :: year,month,date |
|
|
REAL,INTENT(OUT) :: sec |
|
|
|
|
|
INTEGER :: julian_day |
|
|
REAL :: julian_sec |
|
|
!--------------------------------------------------------------------- |
|
|
julian_day = start_day |
|
|
julian_sec = start_sec+REAL(itau)*deltat |
|
|
|
|
|
CALL ju2ymds_internal (julian_day,julian_sec,year,month,date,sec) |
|
|
!----------------------- |
|
|
END SUBROUTINE itau2ymds |
|
|
!- |
|
260 |
!=== |
!=== |
261 |
!- |
|
262 |
SUBROUTINE isittime & |
SUBROUTINE isittime & |
263 |
& (itau,date0,dt,freq,last_action,last_check,do_action) |
& (itau, date0, dt, freq, last_action, last_check, do_action) |
264 |
!--------------------------------------------------------------------- |
|
265 |
!- This subroutine checks the time has come for a given action. |
! This subroutine checks the time has come for a given action. |
266 |
!- This is computed from the current time-step(itau). |
! This is computed from the current time-step(itau). |
267 |
!- Thus we need to have the time delta (dt), the frequency |
! Thus we need to have the time delta (dt), the frequency |
268 |
!- of the action (freq) and the last time it was done |
! of the action (freq) and the last time it was done |
269 |
!- (last_action in units of itau). |
! (last_action in units of itau). |
270 |
!- In order to extrapolate when will be the next check we need |
! In order to extrapolate when will be the next check we need |
271 |
!- the time step of the last call (last_check). |
! the time step of the last call (last_check). |
272 |
|
|
273 |
!- The test is done on the following condition : |
! The test is done on the following condition: |
274 |
!- the distance from the current time to the time for the next |
! the distance from the current time to the time for the next |
275 |
!- action is smaller than the one from the next expected |
! action is smaller than the one from the next expected |
276 |
!- check to the next action. |
! check to the next action. |
277 |
!- When the test is done on the time steps simplifactions make |
! When the test is done on the time steps simplifactions make |
278 |
!- it more difficult to read in the code. |
! it more difficult to read in the code. |
279 |
!- For the real time case it is easier to understand ! |
! For the real time case it is easier to understand ! |
280 |
!--------------------------------------------------------------------- |
|
281 |
IMPLICIT NONE |
INTEGER, INTENT(IN):: itau |
282 |
|
REAL, INTENT(IN):: dt, freq |
283 |
INTEGER,INTENT(IN) :: itau |
INTEGER, INTENT(IN):: last_action, last_check |
284 |
REAL,INTENT(IN) :: dt,freq |
REAL, INTENT(IN):: date0 |
285 |
INTEGER,INTENT(IN) :: last_action,last_check |
|
286 |
REAL,INTENT(IN) :: date0 |
LOGICAL, INTENT(OUT):: do_action |
287 |
|
|
288 |
LOGICAL,INTENT(OUT) :: do_action |
REAL:: dt_action, dt_check |
289 |
|
REAL:: date_last_act, date_next_check, date_next_act, & |
290 |
REAL :: dt_action,dt_check |
& date_now, date_mp1, date_mpf |
291 |
REAL :: date_last_act,date_next_check,date_next_act, & |
INTEGER:: year, month, monthp1, day, next_check_itau, next_act_itau |
292 |
& date_now,date_mp1,date_mpf |
INTEGER:: yearp, dayp |
293 |
INTEGER :: year,month,monthp1,day,next_check_itau,next_act_itau |
REAL:: sec, secp |
294 |
INTEGER :: yearp,dayp |
LOGICAL:: check = .FALSE. |
295 |
REAL :: sec,secp |
!-------------------------------------------------------------------- |
|
LOGICAL :: check = .FALSE. |
|
|
!--------------------------------------------------------------------- |
|
296 |
IF (check) THEN |
IF (check) THEN |
297 |
WRITE(*,*) & |
WRITE(*, *) & |
298 |
& "isittime 1.0 ",itau,date0,dt,freq,last_action,last_check |
& "isittime 1.0 ", itau, date0, dt, freq, last_action, last_check |
299 |
ENDIF |
ENDIF |
300 |
|
|
301 |
IF (last_check >= 0) THEN |
IF (last_check >= 0) THEN |
303 |
dt_check = (itau-last_check)*dt |
dt_check = (itau-last_check)*dt |
304 |
next_check_itau = itau+(itau-last_check) |
next_check_itau = itau+(itau-last_check) |
305 |
|
|
306 |
!-- We are dealing with frequencies in seconds and thus operation |
!- We are dealing with frequencies in seconds and thus operation |
307 |
!-- can be done on the time steps. |
!- can be done on the time steps. |
308 |
|
|
309 |
IF (freq > 0) THEN |
IF (freq > 0) THEN |
310 |
IF (ABS(dt_action-freq) <= ABS(dt_action+dt_check-freq)) THEN |
IF (ABS(dt_action-freq) <= ABS(dt_action+dt_check-freq)) THEN |
313 |
do_action = .FALSE. |
do_action = .FALSE. |
314 |
ENDIF |
ENDIF |
315 |
|
|
316 |
!---- Here we deal with frequencies in month and work on julian days. |
!--- Here we deal with frequencies in month and work on julian days. |
317 |
|
|
318 |
ELSE |
ELSE |
319 |
date_now = itau2date (itau,date0,dt) |
date_now = itau2date (itau, date0, dt) |
320 |
date_last_act = itau2date (last_action,date0,dt) |
date_last_act = itau2date (last_action, date0, dt) |
321 |
CALL ju2ymds (date_last_act,year,month,day,sec) |
CALL ju2ymds (date_last_act, year, month, day, sec) |
322 |
monthp1 = month-freq |
monthp1 = month - freq |
323 |
yearp = year |
yearp = year |
324 |
|
|
325 |
!---- Here we compute what logically should be the next month |
!--- Here we compute what logically should be the next month |
326 |
|
|
327 |
IF (month >= 13) THEN |
IF (month >= 13) THEN |
328 |
yearp = year+1 |
yearp = year+1 |
329 |
monthp1 = monthp1-12 |
monthp1 = monthp1-12 |
330 |
ENDIF |
ENDIF |
331 |
CALL ymds2ju (year,monthp1,day,sec,date_mpf) |
CALL ymds2ju (year, monthp1, day, sec, date_mpf) |
332 |
|
|
333 |
!---- But it could be that because of a shorter month or a bad |
!--- But it could be that because of a shorter month or a bad |
334 |
!---- starting date that we end up further than we should be. |
!--- starting date that we end up further than we should be. |
335 |
!---- Thus we compute the first day of the next month. |
!--- Thus we compute the first day of the next month. |
336 |
!---- We can not be beyond this date and if we are close |
!--- We can not be beyond this date and if we are close |
337 |
!---- then we will take it as it is better. |
!--- then we will take it as it is better. |
338 |
|
|
339 |
monthp1 = month+ABS(freq) |
monthp1 = month+ABS(freq) |
340 |
yearp=year |
yearp=year |
344 |
ENDIF |
ENDIF |
345 |
dayp = 1 |
dayp = 1 |
346 |
secp = 0.0 |
secp = 0.0 |
347 |
CALL ymds2ju (yearp,monthp1,dayp,secp,date_mp1) |
CALL ymds2ju (yearp, monthp1, dayp, secp, date_mp1) |
348 |
|
|
349 |
!---- If date_mp1 is smaller than date_mpf or only less than 4 days |
!--- If date_mp1 is smaller than date_mpf or only less than 4 days |
350 |
!---- larger then we take it. This needed to ensure that short month |
!--- larger then we take it. This needed to ensure that short month |
351 |
!---- like February do not mess up the thing ! |
!--- like February do not mess up the thing ! |
352 |
|
|
353 |
IF (date_mp1-date_mpf < 4.) THEN |
IF (date_mp1-date_mpf < 4.) THEN |
354 |
date_next_act = date_mp1 |
date_next_act = date_mp1 |
355 |
ELSE |
ELSE |
356 |
date_next_act = date_mpf |
date_next_act = date_mpf |
357 |
ENDIF |
ENDIF |
358 |
date_next_check = itau2date (next_check_itau,date0,dt) |
date_next_check = itau2date (next_check_itau, date0, dt) |
359 |
|
|
360 |
!---- Transform the dates into time-steps for the needed precisions. |
!--- Transform the dates into time-steps for the needed precisions. |
361 |
|
|
362 |
next_act_itau = & |
next_act_itau = & |
363 |
& last_action+INT((date_next_act-date_last_act)*(un_jour/dt)) |
& last_action+INT((date_next_act-date_last_act)*(un_jour/dt)) |
364 |
!----- |
|
365 |
IF ( ABS(itau-next_act_itau) & |
IF ( ABS(itau-next_act_itau) & |
366 |
& <= ABS( next_check_itau-next_act_itau)) THEN |
& <= ABS( next_check_itau-next_act_itau)) THEN |
367 |
do_action = .TRUE. |
do_action = .TRUE. |
368 |
IF (check) THEN |
IF (check) THEN |
369 |
WRITE(*,*) & |
WRITE(*, *) & |
370 |
& 'ACT-TIME : itau, next_act_itau, next_check_itau : ', & |
& 'ACT-TIME: itau, next_act_itau, next_check_itau: ', & |
371 |
& itau,next_act_itau,next_check_itau |
& itau, next_act_itau, next_check_itau |
372 |
CALL ju2ymds (date_now,year,month,day,sec) |
CALL ju2ymds (date_now, year, month, day, sec) |
373 |
WRITE(*,*) 'ACT-TIME : y, m, d, s : ',year,month,day,sec |
WRITE(*, *) 'ACT-TIME: y, m, d, s: ', year, month, day, sec |
374 |
WRITE(*,*) & |
WRITE(*, *) & |
375 |
& 'ACT-TIME : date_mp1, date_mpf : ',date_mp1,date_mpf |
& 'ACT-TIME: date_mp1, date_mpf: ', date_mp1, date_mpf |
376 |
ENDIF |
ENDIF |
377 |
ELSE |
ELSE |
378 |
do_action = .FALSE. |
do_action = .FALSE. |
380 |
ENDIF |
ENDIF |
381 |
|
|
382 |
IF (check) THEN |
IF (check) THEN |
383 |
WRITE(*,*) "isittime 2.0 ", & |
WRITE(*, *) "isittime 2.0 ", & |
384 |
& date_next_check,date_next_act,ABS(dt_action-freq), & |
& date_next_check, date_next_act, ABS(dt_action-freq), & |
385 |
& ABS(dt_action+dt_check-freq),dt_action,dt_check, & |
& ABS(dt_action+dt_check-freq), dt_action, dt_check, & |
386 |
& next_check_itau,do_action |
& next_check_itau, do_action |
387 |
ENDIF |
ENDIF |
388 |
ELSE |
ELSE |
389 |
do_action=.FALSE. |
do_action=.FALSE. |
390 |
ENDIF |
ENDIF |
391 |
!---------------------- |
|
392 |
END SUBROUTINE isittime |
END SUBROUTINE isittime |
393 |
!- |
|
394 |
!=== |
!=== |
395 |
!- |
|
396 |
SUBROUTINE ioconf_calendar (str) |
SUBROUTINE ioconf_calendar (str) |
397 |
!--------------------------------------------------------------------- |
|
398 |
!- This routine allows to configure the calendar to be used. |
! This routine allows to configure the calendar to be used. |
399 |
!- This operation is only allowed once and the first call to |
! This operation is only allowed once and the first call to |
400 |
!- ymds2ju or ju2ymsd will lock the current configuration. |
! ymds2ju or ju2ymsd will lock the current configuration. |
401 |
!- the argument to ioconf_calendar can be any of the following : |
! the argument to ioconf_calendar can be any of the following: |
402 |
!- - gregorian : This is the gregorian calendar (default here) |
! - gregorian: This is the gregorian calendar (default here) |
403 |
!- - noleap : A calendar without leap years = 365 days |
! - noleap: A calendar without leap years = 365 days |
404 |
!- - xxxd : A calendar of xxx days (has to be a modulo of 12) |
! - xxxd: A calendar of xxx days (has to be a modulo of 12) |
405 |
!- with 12 month of equal length |
! with 12 month of equal length |
406 |
!--------------------------------------------------------------------- |
|
407 |
IMPLICIT NONE |
CHARACTER(LEN=*), INTENT(IN):: str |
408 |
|
|
409 |
CHARACTER(LEN=*),INTENT(IN) :: str |
INTEGER:: leng, ipos |
410 |
|
CHARACTER(LEN=10):: str10 |
411 |
INTEGER :: leng,ipos |
!-------------------------------------------------------------------- |
|
CHARACTER(LEN=10) :: str10 |
|
|
!--------------------------------------------------------------------- |
|
412 |
|
|
413 |
! 1.0 Clean up the sring ! |
! 1.0 Clean up the sring ! |
414 |
|
|
415 |
CALL strlowercase (str) |
CALL strlowercase (str) |
416 |
|
|
417 |
IF (.NOT.lock_unan) THEN |
IF (.NOT.lock_unan) THEN |
418 |
!--- |
|
419 |
lock_unan=.TRUE. |
lock_unan=.TRUE. |
420 |
!--- |
|
421 |
SELECT CASE(str) |
SELECT CASE(str) |
422 |
CASE('gregorian') |
CASE('gregorian') |
423 |
calendar_used = 'gregorian' |
calendar_used = 'gregorian' |
424 |
un_an = 365.2425 |
un_an = 365.2425 |
425 |
mon_len(:)=(/31,28,31,30,31,30,31,31,30,31,30,31/) |
mon_len(:)=(/31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/) |
426 |
CASE('standard') |
CASE('standard') |
427 |
calendar_used = 'gregorian' |
calendar_used = 'gregorian' |
428 |
un_an = 365.2425 |
un_an = 365.2425 |
429 |
mon_len(:)=(/31,28,31,30,31,30,31,31,30,31,30,31/) |
mon_len(:)=(/31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/) |
430 |
CASE('proleptic_gregorian') |
CASE('proleptic_gregorian') |
431 |
calendar_used = 'gregorian' |
calendar_used = 'gregorian' |
432 |
un_an = 365.2425 |
un_an = 365.2425 |
433 |
mon_len(:)=(/31,28,31,30,31,30,31,31,30,31,30,31/) |
mon_len(:)=(/31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/) |
434 |
CASE('noleap') |
CASE('noleap') |
435 |
calendar_used = 'noleap' |
calendar_used = 'noleap' |
436 |
un_an = 365.0 |
un_an = 365.0 |
437 |
mon_len(:)=(/31,28,31,30,31,30,31,31,30,31,30,31/) |
mon_len(:)=(/31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/) |
438 |
CASE('365_day') |
CASE('365_day') |
439 |
calendar_used = 'noleap' |
calendar_used = 'noleap' |
440 |
un_an = 365.0 |
un_an = 365.0 |
441 |
mon_len(:)=(/31,28,31,30,31,30,31,31,30,31,30,31/) |
mon_len(:)=(/31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/) |
442 |
CASE('365d') |
CASE('365d') |
443 |
calendar_used = 'noleap' |
calendar_used = 'noleap' |
444 |
un_an = 365.0 |
un_an = 365.0 |
445 |
mon_len(:)=(/31,28,31,30,31,30,31,31,30,31,30,31/) |
mon_len(:)=(/31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/) |
446 |
CASE('all_leap') |
CASE('all_leap') |
447 |
calendar_used = 'all_leap' |
calendar_used = 'all_leap' |
448 |
un_an = 366.0 |
un_an = 366.0 |
449 |
mon_len(:)=(/31,29,31,30,31,30,31,31,30,31,30,31/) |
mon_len(:)=(/31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/) |
450 |
CASE('366_day') |
CASE('366_day') |
451 |
calendar_used = 'all_leap' |
calendar_used = 'all_leap' |
452 |
un_an = 366.0 |
un_an = 366.0 |
453 |
mon_len(:)=(/31,29,31,30,31,30,31,31,30,31,30,31/) |
mon_len(:)=(/31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/) |
454 |
CASE('366d') |
CASE('366d') |
455 |
calendar_used = 'all_leap' |
calendar_used = 'all_leap' |
456 |
un_an = 366.0 |
un_an = 366.0 |
457 |
mon_len(:)=(/31,29,31,30,31,30,31,31,30,31,30,31/) |
mon_len(:)=(/31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31/) |
458 |
CASE DEFAULT |
CASE DEFAULT |
459 |
ipos = INDEX(str,'d') |
ipos = INDEX(str, 'd') |
460 |
IF (ipos == 4) THEN |
IF (ipos == 4) THEN |
461 |
READ(str(1:3),'(I3)') leng |
READ(str(1:3), '(I3)') leng |
462 |
IF ( (MOD(leng,12) == 0).AND.(leng > 1) ) THEN |
IF ( (MOD(leng, 12) == 0).AND.(leng > 1) ) THEN |
463 |
calendar_used = str |
calendar_used = str |
464 |
un_an = leng |
un_an = leng |
465 |
mon_len(:) = leng |
mon_len(:) = leng |
466 |
ELSE |
ELSE |
467 |
CALL histerr (3,'ioconf_calendar', & |
CALL histerr (3, 'ioconf_calendar', & |
468 |
& 'The length of the year as to be a modulo of 12', & |
& 'The length of the year as to be a modulo of 12', & |
469 |
& 'so that it can be divided into 12 month of equal length', & |
& 'so that it can be divided into 12 month of equal length', & |
470 |
& str) |
& str) |
471 |
ENDIF |
ENDIF |
472 |
ELSE |
ELSE |
473 |
CALL histerr (3,'ioconf_calendar', & |
CALL histerr (3, 'ioconf_calendar', & |
474 |
& 'Unrecognized input, please ceck the man pages.',str,' ') |
& 'Unrecognized input, please ceck the man pages.', str, ' ') |
475 |
ENDIF |
ENDIF |
476 |
END SELECT |
END SELECT |
477 |
ELSE |
ELSE |
478 |
WRITE(str10,'(f10.4)') un_an |
WRITE(str10, '(f10.4)') un_an |
479 |
CALL histerr (2,'ioconf_calendar', & |
CALL histerr (2, 'ioconf_calendar', & |
480 |
& 'The calendar was already used or configured. You are not', & |
& 'The calendar was already used or configured. You are not', & |
481 |
& 'allowed to change it again. '// & |
& 'allowed to change it again. '// & |
482 |
& 'The following length of year is used :',str10) |
& 'The following length of year is used:', str10) |
483 |
ENDIF |
ENDIF |
|
!----------------------------- |
|
|
END SUBROUTINE ioconf_calendar |
|
|
!- |
|
|
!=== |
|
|
!- |
|
|
SUBROUTINE ioconf_startdate_simple (julian) |
|
|
!--------------------------------------------------------------------- |
|
|
IMPLICIT NONE |
|
|
|
|
|
REAL,INTENT(IN) :: julian |
|
|
|
|
|
INTEGER :: julian_day |
|
|
REAL :: julian_sec |
|
|
!--------------------------------------------------------------------- |
|
|
julian_day = INT(julian) |
|
|
julian_sec = (julian-julian_day)*un_jour |
|
484 |
|
|
485 |
CALL ioconf_startdate_internal (julian_day,julian_sec) |
END SUBROUTINE ioconf_calendar |
|
!------------------------------------- |
|
|
END SUBROUTINE ioconf_startdate_simple |
|
|
!- |
|
|
!=== |
|
|
!- |
|
|
SUBROUTINE ioconf_startdate_ymds (year,month,day,sec) |
|
|
!--------------------------------------------------------------------- |
|
|
IMPLICIT NONE |
|
|
|
|
|
INTEGER,INTENT(IN) :: year,month,day |
|
|
REAL,INTENT(IN) :: sec |
|
|
|
|
|
INTEGER :: julian_day |
|
|
REAL :: julian_sec |
|
|
!--------------------------------------------------------------------- |
|
|
CALL ymds2ju_internal (year,month,day,sec,julian_day,julian_sec) |
|
|
|
|
|
CALL ioconf_startdate_internal (julian_day,julian_sec) |
|
|
!----------------------------------- |
|
|
END SUBROUTINE ioconf_startdate_ymds |
|
|
!- |
|
|
!=== |
|
|
!- |
|
|
SUBROUTINE ioconf_startdate_internal (julian_day,julian_sec) |
|
|
!--------------------------------------------------------------------- |
|
|
! This subroutine allows to set the startdate for later |
|
|
! use. It allows the applications to access the date directly from |
|
|
! the timestep. In order to avoid any problems the start date will |
|
|
! be locked and can not be changed once set. |
|
|
!--------------------------------------------------------------------- |
|
|
IMPLICIT NONE |
|
|
|
|
|
INTEGER,INTENT(IN) :: julian_day |
|
|
REAL,INTENT(IN) :: julian_sec |
|
|
|
|
|
CHARACTER(len=70) :: str70a,str70b |
|
|
!--------------------------------------------------------------------- |
|
|
IF (.NOT.lock_startdate) THEN |
|
|
lock_startdate = .TRUE. |
|
|
start_day = julian_day |
|
|
start_sec = julian_sec |
|
|
ELSE |
|
|
WRITE(str70a,'("The date you tried to set : ",f10.4)') & |
|
|
& julian_day,julian_sec/un_jour |
|
|
WRITE(str70b, & |
|
|
& '("The date which was already set in the calendar : ",f10.4)') & |
|
|
& start_day+start_sec/un_jour |
|
|
CALL histerr (2,'ioconf_startdate', & |
|
|
& 'The start date has already been set and you tried to change it', & |
|
|
& str70a,str70b) |
|
|
ENDIF |
|
|
|
|
|
lock_startdate = .TRUE. |
|
|
!--------------------------------------- |
|
|
END SUBROUTINE ioconf_startdate_internal |
|
|
!- |
|
|
!=== |
|
|
!- |
|
|
SUBROUTINE ioget_calendar_str (str) |
|
|
!--------------------------------------------------------------------- |
|
|
!- This subroutine returns the name of the calendar used here. |
|
|
!- Three options exist : |
|
|
!- - gregorian : This is the gregorian calendar (default here) |
|
|
!- - noleap : A calendar without leap years = 365 days |
|
|
!- - xxxd : A calendar of xxx days (has to be a modulo of 12) |
|
|
!- with 12 month of equal length |
|
|
|
|
|
!- This routine will lock the calendar. |
|
|
!- You do not want it to change after your inquiry. |
|
|
!--------------------------------------------------------------------- |
|
|
IMPLICIT NONE |
|
|
|
|
|
CHARACTER(LEN=*),INTENT(OUT) :: str |
|
|
!--------------------------------------------------------------------- |
|
|
lock_unan = .TRUE. |
|
|
|
|
|
str = calendar_used |
|
|
!-------------------------------- |
|
|
END SUBROUTINE ioget_calendar_str |
|
|
!- |
|
|
!=== |
|
|
!- |
|
|
SUBROUTINE ioget_calendar_real1 (long_an) |
|
|
!--------------------------------------------------------------------- |
|
|
!- This subroutine returns the name of the calendar used here. |
|
|
!- Three options exist : |
|
|
!- - gregorian : This is the gregorian calendar (default here) |
|
|
!- - noleap : A calendar without leap years = 365 days |
|
|
!- - xxxd : A calendar of xxx days (has to be a modulo of 12) |
|
|
!- with 12 month of equal length |
|
|
|
|
|
!- This routine will lock the calendar. |
|
|
!- You do not want it to change after your inquiry. |
|
|
!--------------------------------------------------------------------- |
|
|
IMPLICIT NONE |
|
|
|
|
|
REAL,INTENT(OUT) :: long_an |
|
|
!--------------------------------------------------------------------- |
|
|
lock_unan = .TRUE. |
|
|
|
|
|
long_an = un_an |
|
|
!---------------------------------- |
|
|
END SUBROUTINE ioget_calendar_real1 |
|
|
!- |
|
|
!=== |
|
|
!- |
|
|
SUBROUTINE ioget_calendar_real2 (long_an,long_jour) |
|
|
!--------------------------------------------------------------------- |
|
|
!- This subroutine returns the name of the calendar used here. |
|
|
!- Three options exist : |
|
|
!- - gregorian : This is the gregorian calendar (default here) |
|
|
!- - noleap : A calendar without leap years = 365 days |
|
|
!- - xxxd : A calendar of xxx days (has to be a modulo of 12) |
|
|
!- with 12 month of equal length |
|
|
|
|
|
!- This routine will lock the calendar. |
|
|
!- You do not want it to change after your inquiry. |
|
|
!--------------------------------------------------------------------- |
|
|
IMPLICIT NONE |
|
|
|
|
|
REAL,INTENT(OUT) :: long_an,long_jour |
|
|
!--------------------------------------------------------------------- |
|
|
lock_unan = .TRUE. |
|
|
|
|
|
long_an = un_an |
|
|
long_jour = un_jour |
|
|
!---------------------------------- |
|
|
END SUBROUTINE ioget_calendar_real2 |
|
|
!- |
|
|
!=== |
|
|
!- |
|
|
SUBROUTINE ioget_timestamp (string) |
|
|
!--------------------------------------------------------------------- |
|
|
IMPLICIT NONE |
|
|
|
|
|
CHARACTER(LEN=30),INTENT(OUT) :: string |
|
|
|
|
|
INTEGER :: date_time(8) |
|
|
CHARACTER(LEN=10) :: bigben(3) |
|
|
!--------------------------------------------------------------------- |
|
|
IF (INDEX(time_stamp,'XXXXXX') > 0) THEN |
|
|
CALL DATE_AND_TIME (bigben(1),bigben(2),bigben(3),date_time) |
|
|
!--- |
|
|
WRITE(time_stamp, & |
|
|
& "(I4.4,'-',A3,'-',I2.2,' ',I2.2,':',I2.2,':',I2.2,' GMT',a5)") & |
|
|
& date_time(1),cal(date_time(2)),date_time(3),date_time(5), & |
|
|
& date_time(6),date_time(7),bigben(3) |
|
|
ENDIF |
|
486 |
|
|
|
string = time_stamp |
|
|
!----------------------------- |
|
|
END SUBROUTINE ioget_timestamp |
|
|
!- |
|
|
!=== |
|
|
!- |
|
|
SUBROUTINE time_add & |
|
|
& (year_s,month_s,day_s,sec_s,sec_increment, & |
|
|
& year_e,month_e,day_e,sec_e) |
|
|
!--------------------------------------------------------------------- |
|
|
!- This subroutine allows to increment a date by a number of seconds. |
|
|
!--------------------------------------------------------------------- |
|
|
IMPLICIT NONE |
|
|
|
|
|
INTEGER,INTENT(IN) :: year_s,month_s,day_s |
|
|
REAL,INTENT(IN) :: sec_s |
|
|
!! |
|
|
! Time in seconds to be added to the date |
|
|
!! |
|
|
REAL,INTENT(IN) :: sec_increment |
|
|
|
|
|
INTEGER,INTENT(OUT) :: year_e,month_e,day_e |
|
|
REAL,INTENT(OUT) :: sec_e |
|
|
|
|
|
INTEGER :: julian_day |
|
|
REAL :: julian_sec |
|
|
!--------------------------------------------------------------------- |
|
|
CALL ymds2ju_internal & |
|
|
& (year_s,month_s,day_s,sec_s,julian_day,julian_sec) |
|
|
|
|
|
julian_sec = julian_sec+sec_increment |
|
|
|
|
|
CALL ju2ymds_internal & |
|
|
& (julian_day,julian_sec,year_e,month_e,day_e,sec_e) |
|
|
!---------------------- |
|
|
END SUBROUTINE time_add |
|
|
!- |
|
|
!=== |
|
|
!- |
|
|
SUBROUTINE time_diff & |
|
|
& (year_s,month_s,day_s,sec_s,year_e,month_e,day_e,sec_e,sec_diff) |
|
|
!--------------------------------------------------------------------- |
|
|
!- This subroutine allows to determine the number of seconds |
|
|
!- between two dates. |
|
|
!--------------------------------------------------------------------- |
|
|
IMPLICIT NONE |
|
|
|
|
|
INTEGER,INTENT(IN) :: year_s,month_s,day_s |
|
|
REAL,INTENT(IN) :: sec_s |
|
|
INTEGER,INTENT(IN) :: year_e,month_e,day_e |
|
|
REAL,INTENT(IN) :: sec_e |
|
|
!! |
|
|
! Time in seconds between the two dates |
|
|
!! |
|
|
REAL,INTENT(OUT) :: sec_diff |
|
|
|
|
|
INTEGER :: julian_day_s,julian_day_e,day_diff |
|
|
REAL :: julian_sec_s,julian_sec_e |
|
|
!--------------------------------------------------------------------- |
|
|
CALL ymds2ju_internal & |
|
|
& (year_s,month_s,day_s,sec_s,julian_day_s,julian_sec_s) |
|
|
CALL ymds2ju_internal & |
|
|
& (year_e,month_e,day_e,sec_e,julian_day_e,julian_sec_e) |
|
|
|
|
|
day_diff = julian_day_e-julian_day_s |
|
|
sec_diff = julian_sec_e-julian_sec_s |
|
|
|
|
|
sec_diff = sec_diff+day_diff*un_jour |
|
|
!----------------------- |
|
|
END SUBROUTINE time_diff |
|
|
!- |
|
|
!=== |
|
|
!- |
|
487 |
END MODULE calendar |
END MODULE calendar |