PageRenderTime 42ms CodeModel.GetById 9ms RepoModel.GetById 0ms app.codeStats 1ms

/WPS/util/src/module_date_pack.F

http://github.com/jbeezley/wrf-fire
FORTRAN Legacy | 639 lines | 382 code | 141 blank | 116 comment | 0 complexity | 3497b2081662167d5fb517dd431cd71a MD5 | raw file
Possible License(s): AGPL-1.0
  1. MODULE date_pack
  2. ! This module is able to perform three date and time functions:
  3. ! 1. geth_idts (ndate, odate, idts)
  4. ! Get the time period between two dates.
  5. ! 2. geth_newdate ( ndate, odate, idts)
  6. ! Get the new date based on the old date and a time difference.
  7. ! 3. split_date_char ( date , century_year , month , day , hour , minute , second )
  8. ! Given the date, return the integer components.
  9. use module_debug
  10. CONTAINS
  11. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  12. SUBROUTINE geth_idts (ndate, odate, idts)
  13. IMPLICIT NONE
  14. ! From 2 input mdates ('YYYY-MM-DD HH:MM:SS.ffff'),
  15. ! compute the time difference.
  16. ! on entry - ndate - the new hdate.
  17. ! odate - the old hdate.
  18. ! on exit - idts - the change in time in seconds.
  19. CHARACTER (LEN=*) , INTENT(INOUT) :: ndate, odate
  20. INTEGER , INTENT(OUT) :: idts
  21. ! Local Variables
  22. ! yrnew - indicates the year associated with "ndate"
  23. ! yrold - indicates the year associated with "odate"
  24. ! monew - indicates the month associated with "ndate"
  25. ! moold - indicates the month associated with "odate"
  26. ! dynew - indicates the day associated with "ndate"
  27. ! dyold - indicates the day associated with "odate"
  28. ! hrnew - indicates the hour associated with "ndate"
  29. ! hrold - indicates the hour associated with "odate"
  30. ! minew - indicates the minute associated with "ndate"
  31. ! miold - indicates the minute associated with "odate"
  32. ! scnew - indicates the second associated with "ndate"
  33. ! scold - indicates the second associated with "odate"
  34. ! i - loop counter
  35. ! mday - a list assigning the number of days in each month
  36. CHARACTER (LEN=24) :: tdate
  37. INTEGER :: olen, nlen
  38. INTEGER :: yrnew, monew, dynew, hrnew, minew, scnew
  39. INTEGER :: yrold, moold, dyold, hrold, miold, scold
  40. INTEGER :: mday(12), i, newdys, olddys
  41. LOGICAL :: npass, opass
  42. INTEGER :: isign
  43. IF (odate.GT.ndate) THEN
  44. isign = -1
  45. tdate=ndate
  46. ndate=odate
  47. odate=tdate
  48. ELSE
  49. isign = 1
  50. END IF
  51. ! Assign the number of days in a months
  52. mday( 1) = 31
  53. mday( 2) = 28
  54. mday( 3) = 31
  55. mday( 4) = 30
  56. mday( 5) = 31
  57. mday( 6) = 30
  58. mday( 7) = 31
  59. mday( 8) = 31
  60. mday( 9) = 30
  61. mday(10) = 31
  62. mday(11) = 30
  63. mday(12) = 31
  64. ! Break down old hdate into parts
  65. hrold = 0
  66. miold = 0
  67. scold = 0
  68. olen = LEN(odate)
  69. READ(odate(1:4), '(I4)') yrold
  70. READ(odate(6:7), '(I2)') moold
  71. READ(odate(9:10), '(I2)') dyold
  72. IF (olen.GE.13) THEN
  73. READ(odate(12:13),'(I2)') hrold
  74. IF (olen.GE.16) THEN
  75. READ(odate(15:16),'(I2)') miold
  76. IF (olen.GE.19) THEN
  77. READ(odate(18:19),'(I2)') scold
  78. END IF
  79. END IF
  80. END IF
  81. ! Break down new hdate into parts
  82. hrnew = 0
  83. minew = 0
  84. scnew = 0
  85. nlen = LEN(ndate)
  86. READ(ndate(1:4), '(I4)') yrnew
  87. READ(ndate(6:7), '(I2)') monew
  88. READ(ndate(9:10), '(I2)') dynew
  89. IF (nlen.GE.13) THEN
  90. READ(ndate(12:13),'(I2)') hrnew
  91. IF (nlen.GE.16) THEN
  92. READ(ndate(15:16),'(I2)') minew
  93. IF (nlen.GE.19) THEN
  94. READ(ndate(18:19),'(I2)') scnew
  95. END IF
  96. END IF
  97. END IF
  98. ! Check that the dates make sense.
  99. npass = .true.
  100. opass = .true.
  101. ! Check that the month of NDATE makes sense.
  102. IF ((monew.GT.12).or.(monew.LT.1)) THEN
  103. PRINT*, 'GETH_IDTS: Month of NDATE = ', monew
  104. npass = .false.
  105. END IF
  106. ! Check that the month of ODATE makes sense.
  107. IF ((moold.GT.12).or.(moold.LT.1)) THEN
  108. PRINT*, 'GETH_IDTS: Month of ODATE = ', moold
  109. opass = .false.
  110. END IF
  111. ! Check that the day of NDATE makes sense.
  112. IF (monew.ne.2) THEN
  113. ! ...... For all months but February
  114. IF ((dynew.GT.mday(monew)).or.(dynew.LT.1)) THEN
  115. PRINT*, 'GETH_IDTS: Day of NDATE = ', dynew
  116. npass = .false.
  117. END IF
  118. ELSE IF (monew.eq.2) THEN
  119. ! ...... For February
  120. IF ((dynew.GT.nfeb(yrnew)).OR.(dynew.LT.1)) THEN
  121. PRINT*, 'GETH_IDTS: Day of NDATE = ', dynew
  122. npass = .false.
  123. END IF
  124. END IF
  125. ! Check that the day of ODATE makes sense.
  126. IF (moold.ne.2) THEN
  127. ! ...... For all months but February
  128. IF ((dyold.GT.mday(moold)).or.(dyold.LT.1)) THEN
  129. PRINT*, 'GETH_IDTS: Day of ODATE = ', dyold
  130. opass = .false.
  131. END IF
  132. ELSE IF (moold.eq.2) THEN
  133. ! ....... For February
  134. IF ((dyold.GT.nfeb(yrold)).or.(dyold.LT.1)) THEN
  135. PRINT*, 'GETH_IDTS: Day of ODATE = ', dyold
  136. opass = .false.
  137. END IF
  138. END IF
  139. ! Check that the hour of NDATE makes sense.
  140. IF ((hrnew.GT.23).or.(hrnew.LT.0)) THEN
  141. PRINT*, 'GETH_IDTS: Hour of NDATE = ', hrnew
  142. npass = .false.
  143. END IF
  144. ! Check that the hour of ODATE makes sense.
  145. IF ((hrold.GT.23).or.(hrold.LT.0)) THEN
  146. PRINT*, 'GETH_IDTS: Hour of ODATE = ', hrold
  147. opass = .false.
  148. END IF
  149. ! Check that the minute of NDATE makes sense.
  150. IF ((minew.GT.59).or.(minew.LT.0)) THEN
  151. PRINT*, 'GETH_IDTS: Minute of NDATE = ', minew
  152. npass = .false.
  153. END IF
  154. ! Check that the minute of ODATE makes sense.
  155. IF ((miold.GT.59).or.(miold.LT.0)) THEN
  156. PRINT*, 'GETH_IDTS: Minute of ODATE = ', miold
  157. opass = .false.
  158. END IF
  159. ! Check that the second of NDATE makes sense.
  160. IF ((scnew.GT.59).or.(scnew.LT.0)) THEN
  161. PRINT*, 'GETH_IDTS: SECOND of NDATE = ', scnew
  162. npass = .false.
  163. END IF
  164. ! Check that the second of ODATE makes sense.
  165. IF ((scold.GT.59).or.(scold.LT.0)) THEN
  166. PRINT*, 'GETH_IDTS: Second of ODATE = ', scold
  167. opass = .false.
  168. END IF
  169. IF (.not. npass) THEN
  170. call mprintf(.true.,ERROR,'Screwy NDATE: %s',s1=ndate(1:nlen))
  171. END IF
  172. IF (.not. opass) THEN
  173. call mprintf(.true.,ERROR,'Screwy ODATE: %s',s1=odate(1:olen))
  174. END IF
  175. ! Date Checks are completed. Continue.
  176. ! Compute number of days from 1 January ODATE, 00:00:00 until ndate
  177. ! Compute number of hours from 1 January ODATE, 00:00:00 until ndate
  178. ! Compute number of minutes from 1 January ODATE, 00:00:00 until ndate
  179. newdys = 0
  180. DO i = yrold, yrnew - 1
  181. newdys = newdys + (365 + (nfeb(i)-28))
  182. END DO
  183. IF (monew .GT. 1) THEN
  184. mday(2) = nfeb(yrnew)
  185. DO i = 1, monew - 1
  186. newdys = newdys + mday(i)
  187. END DO
  188. mday(2) = 28
  189. END IF
  190. newdys = newdys + dynew-1
  191. ! Compute number of hours from 1 January ODATE, 00:00:00 until odate
  192. ! Compute number of minutes from 1 January ODATE, 00:00:00 until odate
  193. olddys = 0
  194. IF (moold .GT. 1) THEN
  195. mday(2) = nfeb(yrold)
  196. DO i = 1, moold - 1
  197. olddys = olddys + mday(i)
  198. END DO
  199. mday(2) = 28
  200. END IF
  201. olddys = olddys + dyold-1
  202. ! Determine the time difference in seconds
  203. idts = (newdys - olddys) * 86400
  204. idts = idts + (hrnew - hrold) * 3600
  205. idts = idts + (minew - miold) * 60
  206. idts = idts + (scnew - scold)
  207. IF (isign .eq. -1) THEN
  208. tdate=ndate
  209. ndate=odate
  210. odate=tdate
  211. idts = idts * isign
  212. END IF
  213. END SUBROUTINE geth_idts
  214. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  215. SUBROUTINE geth_newdate (ndate, odate, idt)
  216. IMPLICIT NONE
  217. ! From old date ('YYYY-MM-DD HH:MM:SS.ffff') and
  218. ! delta-time, compute the new date.
  219. ! on entry - odate - the old hdate.
  220. ! idt - the change in time
  221. ! on exit - ndate - the new hdate.
  222. INTEGER , INTENT(IN) :: idt
  223. CHARACTER (LEN=*) , INTENT(OUT) :: ndate
  224. CHARACTER (LEN=*) , INTENT(IN) :: odate
  225. ! Local Variables
  226. ! yrold - indicates the year associated with "odate"
  227. ! moold - indicates the month associated with "odate"
  228. ! dyold - indicates the day associated with "odate"
  229. ! hrold - indicates the hour associated with "odate"
  230. ! miold - indicates the minute associated with "odate"
  231. ! scold - indicates the second associated with "odate"
  232. ! yrnew - indicates the year associated with "ndate"
  233. ! monew - indicates the month associated with "ndate"
  234. ! dynew - indicates the day associated with "ndate"
  235. ! hrnew - indicates the hour associated with "ndate"
  236. ! minew - indicates the minute associated with "ndate"
  237. ! scnew - indicates the second associated with "ndate"
  238. ! mday - a list assigning the number of days in each month
  239. ! i - loop counter
  240. ! nday - the integer number of days represented by "idt"
  241. ! nhour - the integer number of hours in "idt" after taking out
  242. ! all the whole days
  243. ! nmin - the integer number of minutes in "idt" after taking out
  244. ! all the whole days and whole hours.
  245. ! nsec - the integer number of minutes in "idt" after taking out
  246. ! all the whole days, whole hours, and whole minutes.
  247. INTEGER :: nlen, olen
  248. INTEGER :: yrnew, monew, dynew, hrnew, minew, scnew, frnew
  249. INTEGER :: yrold, moold, dyold, hrold, miold, scold, frold
  250. INTEGER :: mday(12), nday, nhour, nmin, nsec, nfrac, i, ifrc
  251. LOGICAL :: opass
  252. CHARACTER (LEN=10) :: hfrc
  253. CHARACTER (LEN=1) :: sp
  254. ! INTEGER, EXTERNAL :: nfeb ! in the same module now
  255. ! Assign the number of days in a months
  256. mday( 1) = 31
  257. mday( 2) = 28
  258. mday( 3) = 31
  259. mday( 4) = 30
  260. mday( 5) = 31
  261. mday( 6) = 30
  262. mday( 7) = 31
  263. mday( 8) = 31
  264. mday( 9) = 30
  265. mday(10) = 31
  266. mday(11) = 30
  267. mday(12) = 31
  268. ! Break down old hdate into parts
  269. hrold = 0
  270. miold = 0
  271. scold = 0
  272. frold = 0
  273. olen = LEN(odate)
  274. IF (olen.GE.11) THEN
  275. sp = odate(11:11)
  276. else
  277. sp = ' '
  278. END IF
  279. ! Use internal READ statements to convert the CHARACTER string
  280. ! date into INTEGER components.
  281. READ(odate(1:4), '(I4)') yrold
  282. READ(odate(6:7), '(I2)') moold
  283. READ(odate(9:10), '(I2)') dyold
  284. IF (olen.GE.13) THEN
  285. READ(odate(12:13),'(I2)') hrold
  286. IF (olen.GE.16) THEN
  287. READ(odate(15:16),'(I2)') miold
  288. IF (olen.GE.19) THEN
  289. READ(odate(18:19),'(I2)') scold
  290. IF (olen.GT.20) THEN
  291. READ(odate(21:olen),'(I2)') frold
  292. END IF
  293. END IF
  294. END IF
  295. END IF
  296. ! Set the number of days in February for that year.
  297. mday(2) = nfeb(yrold)
  298. ! Check that ODATE makes sense.
  299. opass = .TRUE.
  300. ! Check that the month of ODATE makes sense.
  301. IF ((moold.GT.12).or.(moold.LT.1)) THEN
  302. WRITE(*,*) 'GETH_NEWDATE: Month of ODATE = ', moold
  303. opass = .FALSE.
  304. END IF
  305. ! Check that the day of ODATE makes sense.
  306. IF ((dyold.GT.mday(moold)).or.(dyold.LT.1)) THEN
  307. WRITE(*,*) 'GETH_NEWDATE: Day of ODATE = ', dyold
  308. opass = .FALSE.
  309. END IF
  310. ! Check that the hour of ODATE makes sense.
  311. IF ((hrold.GT.23).or.(hrold.LT.0)) THEN
  312. WRITE(*,*) 'GETH_NEWDATE: Hour of ODATE = ', hrold
  313. opass = .FALSE.
  314. END IF
  315. ! Check that the minute of ODATE makes sense.
  316. IF ((miold.GT.59).or.(miold.LT.0)) THEN
  317. WRITE(*,*) 'GETH_NEWDATE: Minute of ODATE = ', miold
  318. opass = .FALSE.
  319. END IF
  320. ! Check that the second of ODATE makes sense.
  321. IF ((scold.GT.59).or.(scold.LT.0)) THEN
  322. WRITE(*,*) 'GETH_NEWDATE: Second of ODATE = ', scold
  323. opass = .FALSE.
  324. END IF
  325. ! Check that the fractional part of ODATE makes sense.
  326. IF (.not.opass) THEN
  327. call mprintf(.true.,ERROR,'GETH_NEWDATE: Crazy ODATE: %s %i',s1=odate(1:olen),i1=olen)
  328. END IF
  329. ! Date Checks are completed. Continue.
  330. ! Compute the number of days, hours, minutes, and seconds in idt
  331. IF (olen.GT.20) THEN !idt should be in fractions of seconds
  332. ifrc = olen-20
  333. ifrc = 10**ifrc
  334. nday = ABS(idt)/(86400*ifrc)
  335. nhour = MOD(ABS(idt),86400*ifrc)/(3600*ifrc)
  336. nmin = MOD(ABS(idt),3600*ifrc)/(60*ifrc)
  337. nsec = MOD(ABS(idt),60*ifrc)/(ifrc)
  338. nfrac = MOD(ABS(idt), ifrc)
  339. ELSE IF (olen.eq.19) THEN !idt should be in seconds
  340. ifrc = 1
  341. nday = ABS(idt)/86400 ! Integer number of days in delta-time
  342. nhour = MOD(ABS(idt),86400)/3600
  343. nmin = MOD(ABS(idt),3600)/60
  344. nsec = MOD(ABS(idt),60)
  345. nfrac = 0
  346. ELSE IF (olen.eq.16) THEN !idt should be in minutes
  347. ifrc = 1
  348. nday = ABS(idt)/1440 ! Integer number of days in delta-time
  349. nhour = MOD(ABS(idt),1440)/60
  350. nmin = MOD(ABS(idt),60)
  351. nsec = 0
  352. nfrac = 0
  353. ELSE IF (olen.eq.13) THEN !idt should be in hours
  354. ifrc = 1
  355. nday = ABS(idt)/24 ! Integer number of days in delta-time
  356. nhour = MOD(ABS(idt),24)
  357. nmin = 0
  358. nsec = 0
  359. nfrac = 0
  360. ELSE IF (olen.eq.10) THEN !idt should be in days
  361. ifrc = 1
  362. nday = ABS(idt)/24 ! Integer number of days in delta-time
  363. nhour = 0
  364. nmin = 0
  365. nsec = 0
  366. nfrac = 0
  367. ELSE
  368. call mprintf(.true.,ERROR,'GETH_NEWDATE: Strange length for ODATE: %i',i1=olen)
  369. END IF
  370. IF (idt.GE.0) THEN
  371. frnew = frold + nfrac
  372. IF (frnew.GE.ifrc) THEN
  373. frnew = frnew - ifrc
  374. nsec = nsec + 1
  375. END IF
  376. scnew = scold + nsec
  377. IF (scnew .GE. 60) THEN
  378. scnew = scnew - 60
  379. nmin = nmin + 1
  380. END IF
  381. minew = miold + nmin
  382. IF (minew .GE. 60) THEN
  383. minew = minew - 60
  384. nhour = nhour + 1
  385. END IF
  386. hrnew = hrold + nhour
  387. IF (hrnew .GE. 24) THEN
  388. hrnew = hrnew - 24
  389. nday = nday + 1
  390. END IF
  391. dynew = dyold
  392. monew = moold
  393. yrnew = yrold
  394. DO i = 1, nday
  395. dynew = dynew + 1
  396. IF (dynew.GT.mday(monew)) THEN
  397. dynew = dynew - mday(monew)
  398. monew = monew + 1
  399. IF (monew .GT. 12) THEN
  400. monew = 1
  401. yrnew = yrnew + 1
  402. ! If the year changes, recompute the number of days in February
  403. mday(2) = nfeb(yrnew)
  404. END IF
  405. END IF
  406. END DO
  407. ELSE IF (idt.LT.0) THEN
  408. frnew = frold - nfrac
  409. IF (frnew .LT. 0) THEN
  410. frnew = frnew + ifrc
  411. nsec = nsec - 1
  412. END IF
  413. scnew = scold - nsec
  414. IF (scnew .LT. 00) THEN
  415. scnew = scnew + 60
  416. nmin = nmin + 1
  417. END IF
  418. minew = miold - nmin
  419. IF (minew .LT. 00) THEN
  420. minew = minew + 60
  421. nhour = nhour + 1
  422. END IF
  423. hrnew = hrold - nhour
  424. IF (hrnew .LT. 00) THEN
  425. hrnew = hrnew + 24
  426. nday = nday + 1
  427. END IF
  428. dynew = dyold
  429. monew = moold
  430. yrnew = yrold
  431. DO i = 1, nday
  432. dynew = dynew - 1
  433. IF (dynew.eq.0) THEN
  434. monew = monew - 1
  435. IF (monew.eq.0) THEN
  436. monew = 12
  437. yrnew = yrnew - 1
  438. ! If the year changes, recompute the number of days in February
  439. mday(2) = nfeb(yrnew)
  440. END IF
  441. dynew = mday(monew)
  442. END IF
  443. END DO
  444. END IF
  445. ! Now construct the new mdate
  446. nlen = LEN(ndate)
  447. IF (nlen.GT.20) THEN
  448. WRITE(ndate(1:19),19) yrnew, monew, dynew, hrnew, minew, scnew
  449. WRITE(hfrc,'(I10)') frnew+1000000000
  450. ndate = ndate(1:19)//'.'//hfrc(31-nlen:10)
  451. ELSE IF (nlen.eq.19.or.nlen.eq.20) THEN
  452. WRITE(ndate(1:19),19) yrnew, monew, dynew, hrnew, minew, scnew
  453. 19 format(I4,'-',I2.2,'-',I2.2,'_',I2.2,':',I2.2,':',I2.2)
  454. IF (nlen.eq.20) ndate = ndate(1:19)//'.'
  455. ELSE IF (nlen.eq.16) THEN
  456. WRITE(ndate,16) yrnew, monew, dynew, hrnew, minew
  457. 16 format(I4,'-',I2.2,'-',I2.2,'_',I2.2,':',I2.2)
  458. ELSE IF (nlen.eq.13) THEN
  459. WRITE(ndate,13) yrnew, monew, dynew, hrnew
  460. 13 format(I4,'-',I2.2,'-',I2.2,'_',I2.2)
  461. ELSE IF (nlen.eq.10) THEN
  462. WRITE(ndate,10) yrnew, monew, dynew
  463. 10 format(I4,'-',I2.2,'-',I2.2)
  464. END IF
  465. IF (olen.GE.11) ndate(11:11) = sp
  466. END SUBROUTINE geth_newdate
  467. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  468. FUNCTION nfeb ( year ) RESULT (num_days)
  469. ! Compute the number of days in February for the given year
  470. IMPLICIT NONE
  471. INTEGER :: year
  472. INTEGER :: num_days
  473. num_days = 28 ! By default, February has 28 days ...
  474. IF (MOD(year,4).eq.0) THEN
  475. num_days = 29 ! But every four years, it has 29 days ...
  476. IF (MOD(year,100).eq.0) THEN
  477. num_days = 28 ! Except every 100 years, when it has 28 days ...
  478. IF (MOD(year,400).eq.0) THEN
  479. num_days = 29 ! Except every 400 years, when it has 29 days.
  480. END IF
  481. END IF
  482. END IF
  483. END FUNCTION nfeb
  484. !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  485. SUBROUTINE split_date_char ( date , century_year , month , day , hour , minute , second )
  486. IMPLICIT NONE
  487. ! Input data.
  488. CHARACTER(LEN=19) , INTENT(IN) :: date
  489. ! Output data.
  490. INTEGER , INTENT(OUT) :: century_year , month , day , hour , minute , second
  491. READ(date,FMT='( I4.4)') century_year
  492. READ(date,FMT='( 5X,I2.2)') month
  493. READ(date,FMT='( 8X,I2.2)') day
  494. READ(date,FMT='(11X,I2.2)') hour
  495. READ(date,FMT='(14X,I2.2)') minute
  496. READ(date,FMT='(17X,I2.2)') second
  497. END SUBROUTINE split_date_char
  498. END MODULE date_pack