SURFEX v8.1
General documentation of Surfex
mode_read_date_netcdf.F90
Go to the documentation of this file.
2 !
3 ! Module to read correctly time in a netcdf file
4 ! Author : Matthieu Lafaysse
5 ! Creation : 2012-11-12
6 ! Modifications
7 !
8 !
9 USE yomhook ,ONLY : lhook, dr_hook
10 USE parkind1 ,ONLY : jprb
11 !
12 IMPLICIT NONE
13 !
14 INTEGER,PARAMETER::iyear_gregoire=1582 !Année où le pape Grégoire XIII décida de passer du calendrier julien au calendrier grégorien
15 !Avant cette date tous les années multiples de 4 sont des années bissextiles
16 !Au-delà de cette date les années multiples de 100 ne sont pas bissextiles sauf les années multiples de 400 qui le sont
17 !De plus les journées du 5 au 14 octobre 1582 ont été supprimées pour compenser le retard accumulé
18 !
19  CONTAINS
20 !
21 !----------------------------------------------------------------------------------------------------------------
22 !
23 SUBROUTINE read_date(PTIME,HUNITS,KYEAR,KMONTH,KDAY,PTIME_DATE)
24 !
25 !* 0.1 Declarations of arguments
26 !
27 REAL,DIMENSION(:),INTENT(IN) :: PTIME
28  CHARACTER(*), INTENT(IN) :: HUNITS
29 !
30 INTEGER, INTENT(OUT) :: KYEAR
31 INTEGER, INTENT(OUT) :: KMONTH
32 INTEGER, INTENT(OUT) :: KDAY
33 REAL, INTENT(OUT) :: PTIME_DATE
34 !
35 !* 0.2 Declarations of local variables
36 !
37 INTEGER,DIMENSION(SIZE(PTIME)) :: ITIMEHOURS
38 REAL, DIMENSION(SIZE(PTIME)) :: ZREST
39 !
40 INTEGER :: IYEAR
41 INTEGER :: IMONTH
42 INTEGER :: IDAY
43 INTEGER :: IHOUR
44 REAL :: ZTIME
45 !
46  CHARACTER(LEN=14) :: YHEADER
47  CHARACTER(LEN=100) :: YFMT
48  CHARACTER :: YC1,YC2,YC3
49 !
50 LOGICAL :: GHEADER
51 !
52 INTEGER,DIMENSION(4),PARAMETER :: ITV_DATEREF = (/1900,1,1,0/)
53 INTEGER,DIMENSION(4),PARAMETER :: ITV_DATEREFBIS = (/1850,1,1,0/)
54 !
55 INTEGER,DIMENSION(4) :: ITV_DATETEMPO
56 INTEGER :: ICARACUNITS,ICARACHOUR,ICARACDAY,ICARACMONTH,ICARACYEAR
57 INTEGER :: IERROR
58 INTEGER :: IV_DIFFREF
59 !
60 REAL(KIND=JPRB) :: ZHOOK_HANDLE
61 !
62 !-------------------------------------------------------------------------------
63 !
64 IF (lhook) CALL dr_hook('MODE_TRIP_DATE_NETCDF:READ_DATE',0,zhook_handle)
65 !
66 SELECT CASE (hunits(1:4))
67  CASE ("days")
68  icaracunits = 11
69  itimehours(:) = int(ptime(:)*24.)
70  zrest(:) = ptime(:)*24.-itimehours(:)
71  CASE ("hour")
72  icaracunits = 12
73  itimehours(:) = int(ptime(:))
74  zrest(:) = ptime(:)-itimehours(:)
75  CASE ("minu")
76  icaracunits = 14
77  itimehours(:) = int(ptime(:)/60.)
78  zrest(:) = (ptime(:)/60.)-itimehours(:)
79  CASE ("seco")
80  icaracunits = 14
81  itimehours(:) = int(ptime(:)/3600.)
82  zrest(:) = (ptime(:)/3600.)-itimehours(:)
83  CASE DEFAULT
84  print*, "ERROR date_netcdf.F90 : Can't read time units :"
85  print*,trim(hunits)
86  stop "Error units time"
87 END SELECT
88 !
89 ! * Read reference date
90 !
91 SELECT CASE (hunits(1:4))
92  CASE ("days","hour","minu","seco")
93  boucles_hours:DO icarachour=1,2 !Hour written by 1 or 2 char
94  DO icaracday=1,2 !Day written by 1 or 2 char
95  DO icaracmonth=1,2 !Month written by 1 or 2 char
96  DO icaracyear=1,4 !Year written by 1 to 4 char
97  WRITE(yfmt,fmt='("(A",I2,",",2("I",I1,",A1,"),"I",I1,",X,I",I1,",A1)")')&
98  icaracunits,icaracyear,icaracmonth,icaracday,icarachour
99  READ(hunits,fmt=yfmt,iostat=ierror)yheader,iyear,&
100  yc1,imonth,yc2,iday,ihour,yc3
101  IF (ierror==0) THEN
102  gheader=(trim(yheader)=='hours since') .OR. (trim(yheader)=='minutes since') .OR. &
103  (trim(yheader)=='seconds since') .OR. (trim(yheader)=='days since')
104  IF (gheader.AND.(yc1=='-').AND.(yc2=='-').AND.(yc3==':')) THEN
105  EXIT boucles_hours
106  END IF
107  END IF
108  END DO
109  END DO
110  END DO
111  END DO boucles_hours
112  CASE DEFAULT
113  stop "Error units time"
114 END SELECT
115 !
116 ! * Check successful reading
117 !
118 IF (ierror>0) THEN
119  print*, "ERROR date_netcdf.F90 : Can't read time units :"
120  print*,trim(hunits)
121  stop "Error units time"
122 END IF
123 !
124 !Initialiaze the date to the reference date
125 !
126 ztime = REAL(ihour)+ZREST(1)
127 !
128 !Add the number of hours to a date
129 !
130  CALL addtime(itimehours(1),iyear,imonth,iday,ztime)
131 !
132 ! Current date
133 !
134 kyear = iyear
135 kmonth = imonth
136 kday = iday
137 ptime_date = ztime
138 !
139 IF (lhook) CALL dr_hook('MODE_TRIP_DATE_NETCDF:READ_DATE',1,zhook_handle)
140 
141 END SUBROUTINE read_date
142 !
143 !----------------------------------------------------------------------------------------------------------------
144 !
145 SUBROUTINE addtime (KNHOURS,KYEAR,KMONTH,KDAY,PTIME)
146 !
147 !* 0.1 Declarations of arguments
148 !
149 INTEGER, INTENT(IN) :: KNHOURS ! number of hours
150 !
151 INTEGER, INTENT(OUT) :: KYEAR
152 INTEGER, INTENT(OUT) :: KMONTH
153 INTEGER, INTENT(OUT) :: KDAY
154 REAL, INTENT(OUT) :: PTIME
155 !
156 !* 0.2 Declarations of local variables
157 !
158 INTEGER,DIMENSION(12) :: INBDM !Number of days per months
159 INTEGER :: IREMAININGDAYS !Number of remaining days to add
160 !
161 REAL(KIND=JPRB) :: ZHOOK_HANDLE
162 !
163 !-------------------------------------------------------------------------------
164 !
165 IF (lhook) CALL dr_hook('MODE_TRIP_DATE_NETCDF:ADDTIME',0,zhook_handle)
166 !
167 !special case of year 1582
168 !
169 IF (kyear==iyear_gregoire) THEN
170  inbdm=(/31,28,31,30,31,30,31,31,30,21,30,31/)
171 ELSE
172  IF (leapyear(kyear)) THEN
173  inbdm=(/31,29,31,30,31,30,31,31,30,31,30,31/)
174  ELSE
175  inbdm=(/31,28,31,30,31,30,31,31,30,31,30,31/)
176  ENDIF
177 ENDIF
178 !
179 IF (knhours>=0) THEN
180  !Increase hour
181  IF ((int(ptime)+knhours)<=23) THEN
182  ptime=ptime+knhours
183  ELSE
184  iremainingdays=(int(ptime)+knhours)/24 !Number of remaining days
185  ptime=mod(int(ptime)+knhours,24)+ptime-int(ptime) ! new hour (+minutes)
186  !Increase days
187  DO
188  IF ((kday+iremainingdays)<=inbdm(kmonth)) THEN
189  kday=kday+iremainingdays
190  EXIT
191  ELSE
192  iremainingdays=iremainingdays-(inbdm(kmonth)-kday+1)
193  IF (kmonth<12) THEN
194  kmonth=kmonth+1 !Month change
195  kday=1
196  ELSE
197  !Year change
198  kyear=kyear+1
199  kmonth=1
200  kday=1
201  !Update february number of days
202  IF (leapyear(kyear)) inbdm(2)=29
203  IF (leapyear(kyear-1)) inbdm(2)=28
204  !Update october month for 1582 and 1583
205  IF (kyear==iyear_gregoire) inbdm(10)=21
206  IF (kyear==iyear_gregoire+1) inbdm(10)=31
207  ENDIF
208  ENDIF
209  ENDDO
210  ENDIF
211 ELSE
212  IF ((int(ptime)+knhours)>=0) THEN
213  ptime=ptime+knhours
214  ELSE
215  iremainingdays=(int(ptime)-knhours)/24+1
216  ptime=mod(int(ptime)-knhours,24)+ptime-int(ptime) ! new hour
217  ! decrease days
218  DO
219  IF ((kday-iremainingdays)>=1) THEN
220  kday=kday-iremainingdays
221  EXIT
222  ELSE
223  iremainingdays=iremainingdays-kday
224  IF (kmonth>=1) THEN
225  kmonth=kmonth-1 !Month change
226  kday=inbdm(kmonth)
227  ELSE
228  !Year change
229  kyear=kyear-1
230  kmonth=12
231  kday=inbdm(kmonth)
232  !Update february number of days
233  IF (leapyear(kyear)) inbdm(2)=29
234  IF (leapyear(kyear+1)) inbdm(2)=28
235  !Update october month for 1582 and 1583
236  IF (kyear==iyear_gregoire) inbdm(10)=21
237  IF (kyear==iyear_gregoire-1) inbdm(10)=31
238  END IF
239  END IF
240  END DO
241  END IF
242 END IF
243 !
244 IF (lhook) CALL dr_hook('MODE_TRIP_DATE_NETCDF:ADDTIME',1,zhook_handle)
245 !
246 END SUBROUTINE addtime
247 !
248 !--------------------------------------------------------------------------------------------------------------
249 !
250 LOGICAL FUNCTION leapyear (PYEAR)
251 INTEGER, INTENT(IN) :: PYEAR ! Is the year a leap year ?
252 REAL(KIND=JPRB) :: ZHOOK_HANDLE
253 !
254 IF (lhook) CALL dr_hook('MODE_TRIP_DATE_NETCDF:LEAPYEAR',0,zhook_handle)
255 !
256 IF (pyear>iyear_gregoire) THEN
257  leapyear = (((mod(pyear,4)==0).AND.(mod(pyear,100)/=0)).OR.(mod(pyear,400)==0))
258 ELSE
259  leapyear = (mod(pyear,4)==0)
260 ENDIF
261 !
262 IF (lhook) CALL dr_hook('MODE_TRIP_DATE_NETCDF:LEAPYEAR',1,zhook_handle)
263 !
264 END FUNCTION leapyear
265 !
266 !--------------------------------------------------------------------------------------------------------------
267 !
268 END MODULE mode_trip_date_netcdf
static const char * trim(const char *name, int *n)
Definition: drhook.c:2383
integer, parameter jprb
Definition: parkind1.F90:32
subroutine read_date(PTIME, HUNITS, KYEAR, KMONTH, KDAY, PTIME_DATE)
logical lhook
Definition: yomhook.F90:15
subroutine addtime(KNHOURS, KYEAR, KMONTH, KDAY, PTIME)
logical function leapyear(PYEAR)
integer, parameter iyear_gregoire