SURFEX  V8_0
Surfex V8_0 release
 All Classes Files Functions Variables
mode_dates_netcdf.F90
Go to the documentation of this file.
1 !SFX_LIC Copyright 1994-2014 CNRS, Meteo-France and Universite Paul Sabatier
2 !SFX_LIC This is part of the SURFEX software governed by the CeCILL-C licence
3 !SFX_LIC version 1. See LICENSE, CeCILL-C_V1-en.txt and CeCILL-C_V1-fr.txt
4 !SFX_LIC for details. version 1.
6 
7 ! Module to read correctly time in a netcdf file
8 
9 ! Author : Matthieu Lafaysse
10 ! Creation : 2012-11-12
11 
12 ! Modifications
13 
15 
16 USE yomhook ,ONLY : lhook, dr_hook
17 USE parkind1 ,ONLY : jprb
18 
19 IMPLICIT NONE
20 
21 INTEGER,PARAMETER::JP_GREGOIRE=1582 !Année où le pape Grégoire XIII décida de passer du calendrier julien au calendrier grégorien
22 !Avant cette date tous les années multiples de 4 sont des années bissextiles
23 !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
24 !De plus les journées du 5 au 14 octobre 1582 ont été supprimées pour compenser le retard accumulé
25 
26 
27  CONTAINS
28 
29 !----------------------------------------------------------------------------------------------------------------
30 
31 
32 SUBROUTINE netcdf2date(PTIME,HUNITS,PDATETIME)
33 !
34 ! Conversion de la date au format netcdf vers le format année mois jour heure selon dimension de itv_date
35 REAL,DIMENSION(:),INTENT(IN) :: ptime
36  CHARACTER(*),INTENT(IN) :: hunits
37 TYPE (date_time),DIMENSION(:),INTENT(OUT) :: pdatetime
38 !
39 INTEGER,DIMENSION(SIZE(PTIME)) :: itimehours
40 REAL,DIMENSION(SIZE(PTIME)) :: zrest
41 INTEGER :: iyearunits,imonthunits,idayunits,ihourunits
42 !
43  CHARACTER(LEN=14) :: yheader
44  CHARACTER(LEN=100) :: yfmt
45  CHARACTER :: yc1,yc2,yc3
46 !
47 LOGICAL :: gheader
48 !
49 INTEGER,DIMENSION(4),PARAMETER :: itv_dateref = (/1900,1,1,0/)
50 INTEGER,DIMENSION(4),PARAMETER :: itv_daterefbis = (/1850,1,1,0/)
51 !
52 INTEGER,DIMENSION(4) :: itv_datetempo
53 INTEGER :: icaracunits,icarachour,icaracday,icaracmonth,icaracyear
54 INTEGER :: ierror
55 INTEGER :: jtime
56 INTEGER :: iv_diffref
57 !
58 REAL(KIND=JPRB) :: zhook_handle
59 !
60 IF (lhook) CALL dr_hook('MODE_DATES_NETCDF:NETCDF2DATE',0,zhook_handle)
61 !
62 SELECT CASE (hunits(1:4))
63  CASE ("days")
64  icaracunits = 11
65  itimehours = int(ptime*24.)
66  zrest = ptime*24.-itimehours
67  CASE ("hour")
68  icaracunits = 12
69  itimehours = int(ptime)
70  zrest = ptime-itimehours
71  CASE ("minu")
72  icaracunits = 14
73  itimehours = int(ptime/60.)
74  zrest = (ptime/60.)-itimehours
75  CASE ("seco")
76  icaracunits = 14
77  itimehours = int(ptime/3600.)
78  zrest = (ptime/3600.)-itimehours
79  CASE default
80  print*, "ERROR date_netcdf.F90 : Can't read time units :"
81  print*,trim(hunits)
82  stop "Error units time"
83 END SELECT
84 
85 SELECT CASE (hunits(1:4))
86  !CASE ("days")
87  ! !Read reference date
88  ! boucles_days:DO ICARACDAY=1,2 !Day written by 1 or 2 char
89  ! DO ICARACMONTH=1,2 !Month written by 1 or 2 char
90  ! DO ICARACYEAR=1,4 !Year written by 1 to 4 char
91  ! WRITE(YFMT,FMT='("(A",I2,",",2("I",I1,",A1,"),"I",I1,",X,I",I1,",A1)")')&
92  ! ICARACUNITS,ICARACYEAR,ICARACMONTH,ICARACDAY,ICARACHOUR
93  ! READ(HUNITS,FMT=YFMT,IOSTAT=IERROR)YHEADER,IYEARUNITS,YC1,IMONTHUNITS,YC2,IDAYUNITS,IHOURUNITS,YC3
94  ! IHOURUNITS=0
95  ! IF (IERROR==0) THEN
96  ! IF ((TRIM(YHEADER)=='days since').AND.(YC1=='-').AND.(YC2=='-').AND.(YC3==':')) THEN
97  ! ! PRINT*,"DATE DE REFERENCE LUE :"
98  ! ! PRINT*,itv_oldref
99  ! EXIT boucles_days
100  ! END IF
101  ! END IF
102  ! END DO
103  ! END DO
104  ! END DO boucles_days
105  CASE ("days","hour","minu","seco")
106  !Read reference date
107  boucles_hours:DO icarachour=1,2 !Hour written by 1 or 2 char
108  DO icaracday=1,2 !Day written by 1 or 2 char
109  DO icaracmonth=1,2 !Month written by 1 or 2 char
110  DO icaracyear=1,4 !Year written by 1 to 4 char
111  WRITE(yfmt,fmt='("(A",I2,",",2("I",I1,",A1,"),"I",I1,",X,I",I1,",A1)")')&
112  icaracunits,icaracyear,icaracmonth,icaracday,icarachour
113  READ(hunits,fmt=yfmt,iostat=ierror)yheader,iyearunits,&
114  yc1,imonthunits,yc2,idayunits,ihourunits,yc3
115  IF (ierror==0) THEN
116  gheader=(trim(yheader)=='hours since') .OR. (trim(yheader)=='minutes since') .OR. &
117  (trim(yheader)=='seconds since') .OR. (trim(yheader)=='days since')
118  IF (gheader.AND.(yc1=='-').AND.(yc2=='-').AND.(yc3==':')) THEN
119  ! PRINT*,"DATE DE REFERENCE LUE :"
120  ! PRINT*,itv_oldref
121  EXIT boucles_hours
122  END IF
123  END IF
124  END DO
125  END DO
126  END DO
127  END DO boucles_hours
128  CASE default
129  stop "Error units time"
130 END SELECT
131 
132 
133 
134 !Check successful reading
135 IF (ierror>0) THEN
136  print*, "ERROR date_netcdf.F90 : Can't read time units :"
137  print*,trim(hunits)
138  stop "Error units time"
139 END IF
140 
141 DO jtime=1,SIZE(ptime)
142  !Initialiaze the date to the reference date
143  pdatetime(jtime)%TDATE%YEAR = iyearunits
144  pdatetime(jtime)%TDATE%MONTH = imonthunits
145  pdatetime(jtime)%TDATE%DAY = idayunits
146  pdatetime(jtime)%TIME = ihourunits+zrest(jtime)
147  CALL addhours(pdatetime(jtime),itimehours(jtime))
148 END DO
149 
150 IF (lhook) CALL dr_hook('MODE_DATES_NETCDF:NETCDF2DATE',1,zhook_handle)
151 
152 END SUBROUTINE netcdf2date
153 !----------------------------------------------------------------------------------------------------------------
154 
155 !--------------------------------------------------------------------------------------------------------------
156 LOGICAL FUNCTION leapyear (PYEAR)
157 INTEGER, INTENT(IN) :: pyear ! Is the year a leap year ?
158 REAL(KIND=JPRB) :: zhook_handle
159 
160 IF (lhook) CALL dr_hook('MODE_DATES_NETCDF:LEAPYEAR',0,zhook_handle)
161 
162 IF (pyear>jp_gregoire) THEN
163  leapyear = (((mod(pyear,4)==0).AND.(mod(pyear,100)/=0)).OR.(mod(pyear,400)==0))
164 ELSE
165  leapyear = (mod(pyear,4)==0)
166 ENDIF
167 
168 IF (lhook) CALL dr_hook('MODE_DATES_NETCDF:LEAPYEAR',1,zhook_handle)
169 
170 END FUNCTION leapyear
171 !--------------------------------------------------------------------------------------------------------------
172 
173 !--------------------------------------------------------------------------------------------------------------
174 SUBROUTINE addhours (TPTIME,KNHOURS)
175 !Add the number of hours to a date
176 TYPE(date_time),INTENT(INOUT)::tptime
177 INTEGER,INTENT(IN)::knhours ! number of hours
178 INTEGER,DIMENSION(12)::inbdm !Number of days per months
179 INTEGER::iremainingdays !Number of remaining days to add
180 REAL(KIND=JPRB) :: zhook_handle
181 
182 IF (lhook) CALL dr_hook('MODE_DATES_NETCDF:ADDHOURS',0,zhook_handle)
183 
184 !special case of 1582
185 IF (tptime%TDATE%YEAR==jp_gregoire) THEN
186  inbdm=(/31,28,31,30,31,30,31,31,30,21,30,31/)
187 ELSE
188  IF (leapyear(tptime%TDATE%YEAR)) THEN
189  inbdm=(/31,29,31,30,31,30,31,31,30,31,30,31/)
190  ELSE
191  inbdm=(/31,28,31,30,31,30,31,31,30,31,30,31/)
192  ENDIF
193 ENDIF
194 
195 IF (knhours>=0) THEN
196  !Increase hour
197  IF ((int(tptime%TIME)+knhours)<=23) THEN
198  tptime%TIME=tptime%TIME+knhours
199  ELSE
200  iremainingdays=(int(tptime%TIME)+knhours)/24 !Number of remaining days
201  tptime%TIME=mod(int(tptime%TIME)+knhours,24)+tptime%TIME-int(tptime%TIME) ! new hour (+minutes)
202  !Increase days
203  DO
204  IF ((tptime%TDATE%DAY+iremainingdays)<=inbdm(tptime%TDATE%MONTH)) THEN
205  tptime%TDATE%DAY=tptime%TDATE%DAY+iremainingdays
206  EXIT
207  ELSE
208  iremainingdays=iremainingdays-(inbdm(tptime%TDATE%MONTH)-tptime%TDATE%DAY+1)
209  IF (tptime%TDATE%MONTH<12) THEN
210  tptime%TDATE%MONTH=tptime%TDATE%MONTH+1 !Month change
211  tptime%TDATE%DAY=1
212  ELSE
213  !Year change
214  tptime%TDATE%YEAR=tptime%TDATE%YEAR+1
215  tptime%TDATE%MONTH=1
216  tptime%TDATE%DAY=1
217  !Update february number of days
218  IF (leapyear(tptime%TDATE%YEAR)) inbdm(2)=29
219  IF (leapyear(tptime%TDATE%YEAR-1)) inbdm(2)=28
220  !Update october month for 1582 and 1583
221  IF (tptime%TDATE%YEAR==jp_gregoire) inbdm(10)=21
222  IF (tptime%TDATE%YEAR==jp_gregoire+1) inbdm(10)=31
223  ENDIF
224  ENDIF
225  ENDDO
226  ENDIF
227 ELSE
228  IF ((int(tptime%TIME)+knhours)>=0) THEN
229  tptime%TIME=tptime%TIME+knhours
230  ELSE
231  iremainingdays=(int(tptime%TIME)-knhours)/24+1
232  tptime%TIME=mod(int(tptime%TIME)-knhours,24)+tptime%TIME-int(tptime%TIME) ! new hour
233  ! decrease days
234  DO
235  IF ((tptime%TDATE%DAY-iremainingdays)>=1) THEN
236  tptime%TDATE%DAY=tptime%TDATE%DAY-iremainingdays
237  EXIT
238  ELSE
239  iremainingdays=iremainingdays-tptime%TDATE%DAY
240  IF (tptime%TDATE%MONTH>=1) THEN
241  tptime%TDATE%MONTH=tptime%TDATE%MONTH-1 !Month change
242  tptime%TDATE%DAY=inbdm(tptime%TDATE%MONTH)
243  ELSE
244  !Year change
245  tptime%TDATE%YEAR=tptime%TDATE%YEAR-1
246  tptime%TDATE%MONTH=12
247  tptime%TDATE%DAY=inbdm(tptime%TDATE%MONTH)
248  !Update february number of days
249  IF (leapyear(tptime%TDATE%YEAR)) inbdm(2)=29
250  IF (leapyear(tptime%TDATE%YEAR+1)) inbdm(2)=28
251  !Update october month for 1582 and 1583
252  IF (tptime%TDATE%YEAR==jp_gregoire) inbdm(10)=21
253  IF (tptime%TDATE%YEAR==jp_gregoire-1) inbdm(10)=31
254  END IF
255  END IF
256  END DO
257  END IF
258 END IF
259 
260 IF (lhook) CALL dr_hook('MODE_DATES_NETCDF:ADDHOURS',1,zhook_handle)
261 
262 END SUBROUTINE addhours
263 !--------------------------------------------------------------------------------------------------------------
264 
265 END MODULE mode_dates_netcdf
subroutine addhours(TPTIME, KNHOURS)
LOGICAL function leapyear(PYEAR)
subroutine netcdf2date(PTIME, HUNITS, PDATETIME)