SCALE-RM
scale_calendar.F90
Go to the documentation of this file.
1 !-------------------------------------------------------------------------------
11 !-------------------------------------------------------------------------------
12 #include "scalelib.h"
14  !-----------------------------------------------------------------------------
15  !
16  !++ used modules
17  !
18  use scale_precision
19  use scale_io
20  !-----------------------------------------------------------------------------
21  implicit none
22  private
23  !-----------------------------------------------------------------------------
24  !
25  !++ Public procedure
26  !
27  public :: calendar_setup
28  public :: calendar_getdayofyear
29  public :: calendar_date2daysec
30  public :: calendar_daysec2date
31  public :: calendar_ymd2absday
32  public :: calendar_hms2abssec
33  public :: calendar_adjust_daysec
34  public :: calendar_combine_daysec
35  public :: calendar_unit2sec
36  public :: calendar_sec2unit
37  public :: calendar_cfunits2sec
38  public :: calendar_date2char
39  public :: calendar_get_name
40 
41  !-----------------------------------------------------------------------------
42  !
43  !++ Public parameters & variables
44  !
45  integer, public, parameter :: i_year = 1
46  integer, public, parameter :: i_month = 2
47  integer, public, parameter :: i_day = 3
48  integer, public, parameter :: i_hour = 4
49  integer, public, parameter :: i_min = 5
50  integer, public, parameter :: i_sec = 6
51 
52  real(dp), public :: calendar_doi = 365.0_dp
53  real(dp), public :: calendar_hour = 24.0_dp
54  real(dp), public :: calendar_min = 60.0_dp
55  real(dp), public :: calendar_sec = 60.0_dp
56 
57  !-----------------------------------------------------------------------------
58  !
59  !++ Private procedure
60  !
61  private :: calendar_absday2ymd
62  private :: calendar_abssec2hms
63  private :: calendar_ymdhms2nd
64  private :: calendar_ymdhms2mjd
65  private :: checkleap
66 
67  !-----------------------------------------------------------------------------
68  !
69  !++ Private parameters & variables
70  !
71  logical, private :: calendar_360days = .false.
72  logical, private :: calendar_365days = .false.
73  logical, private :: calendar_user = .false.
74 
75  integer, private, parameter :: i_nonleapyear = 1
76  integer, private, parameter :: i_leapyear = 2
77  integer, private, parameter :: i_360days = 3
78  integer, private, parameter :: i_user = 4
79 
80  integer, private :: dayofmonth(12,4)
81  data dayofmonth / 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, & ! non-leap year
82  31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, & ! leap year
83  30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, & ! 360 days
84  -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 / ! for CALENDAR_USER_DEFINED
85 
86  integer, private :: calendar_user_defined(12)
87  integer, private :: calendar_month = 12
88  logical, private :: debug = .false.
89 
90  !-----------------------------------------------------------------------------
91 contains
92  !-----------------------------------------------------------------------------
94  subroutine calendar_setup
95  use scale_prc, only: &
96  prc_abort
97  implicit none
98 
99  namelist / param_calendar / &
100  calendar_360days, &
101  calendar_365days, &
102  calendar_hour, &
103  calendar_min, &
104  calendar_sec, &
105  calendar_user_defined, &
106  debug
107 
108  integer :: ierr, i
109  !---------------------------------------------------------------------------
110 
111  log_newline
112  log_info("CALENDAR_setup",*) 'Setup'
113 
114  calendar_user_defined(:) = 0
115 
116  !--- read namelist
117  rewind(io_fid_conf)
118  read(io_fid_conf,nml=param_calendar,iostat=ierr)
119  if( ierr < 0 ) then !--- missing
120  log_info("CALENDAR_setup",*) 'Not found namelist. Default used.'
121  elseif( ierr > 0 ) then !--- fatal error
122  log_error("CALENDAR_setup",*) 'Not appropriate names in namelist PARAM_CALENDAR. Check!'
123  call prc_abort
124  endif
125  log_nml(param_calendar)
126 
127  log_newline
128  log_info("CALENDAR_setup",*) 'Calendar settings'
129  if ( maxval(calendar_user_defined) > 0 ) then
130  dayofmonth(:,i_user) = calendar_user_defined(:)
131  calendar_doi = sum(calendar_user_defined)
132  calendar_user = .true.
133  log_info_cont(*) 'DayOfYear = ', int(calendar_doi), ' : user defined calendar'
134  do i = 1, 12
135  if ( calendar_user_defined(i) > 0 ) then
136  log_info_cont(*) 'month #', i, ': ', calendar_user_defined(i), "days"
137  else
138  calendar_month = i - 1
139  exit
140  endif
141  enddo
142  elseif( calendar_360days ) then
143  calendar_doi = 360.0_dp
144  log_info_cont(*) 'DayOfYear = 360 : ideal setting'
145  elseif( calendar_365days ) then
146  calendar_doi = 365.0_dp
147  log_info_cont(*) 'DayOfYear = 365 : ideal setting'
148  else
149  log_info_cont(*) 'DayOfYear = 365 or 366 : Gregorian calendar'
150  endif
151 
152  if (int(calendar_sec) /= calendar_sec .or. int(calendar_sec) == 0 ) then
153  log_error("CALENDAR_setup",*) 'CALENDAR_SEC must be a natural number!'
154  call abort
155  elseif (int(calendar_min) /= calendar_min .or. int(calendar_min) == 0 ) then
156  log_error("CALENDAR_setup",*) 'CALENDAR_MIN must be a natural number!'
157  call abort
158  elseif (int(calendar_hour) /= calendar_hour .or. int(calendar_hour) == 0 ) then
159  log_error("CALENDAR_setup",*) 'CALENDAR_HOUR must be a natural number!'
160  call abort
161  endif
162 
163 
164  return
165  end subroutine calendar_setup
166 
167  !-----------------------------------------------------------------------------
169  subroutine calendar_getdayofyear( &
170  DayOfYear, &
171  iyear )
172  implicit none
173 
174  real(dp), intent(out) :: dayofyear ! # of day of year
175  integer, intent(in) :: iyear ! current year
176  !---------------------------------------------------------------------------
177 
178  dayofyear = calendar_doi
179  if( checkleap(iyear) ) dayofyear = calendar_doi + 1.0_dp
180 
181  return
182  end subroutine calendar_getdayofyear
183 
184  !-----------------------------------------------------------------------------
186  subroutine calendar_date2daysec( &
187  absday, &
188  abssec, &
189  ymdhms, &
190  subsec, &
191  offset_year )
192  implicit none
193 
194  integer, intent(out) :: absday
195  real(dp), intent(out) :: abssec
196  integer, intent(in) :: ymdhms(6)
197  real(dp), intent(in) :: subsec
198  integer, intent(in) :: offset_year
199  integer :: ileap
200  logical :: date_error = .false.
201  !---------------------------------------------------------------------------
202 
203  ! check date
204  if ( ymdhms(i_month) < 1 .or. calendar_month < ymdhms(i_month) ) then
205  log_error("CALENDAR_date2daysec",*) 'Inputted month does not match to the calendar.'
206  date_error = .true.
207  endif
208 
209  ileap = i_nonleapyear
210  if( checkleap(ymdhms(i_year)+offset_year) ) ileap = i_leapyear
211  if( calendar_360days ) ileap = i_360days
212  if( calendar_user ) ileap = i_user
213 
214  if ( ymdhms(i_day ) < 1 .or. dayofmonth(ymdhms(i_month),ileap) < ymdhms(i_day) ) then
215  log_error("CALENDAR_date2daysec",*) 'Inputted day does not match to the calendar.'
216  date_error = .true.
217  endif
218  if ( ymdhms(i_hour) < 0 .or. (int(calendar_hour)-1) < ymdhms(i_hour) ) then
219  log_error("CALENDAR_date2daysec",*) 'Inputted hour does not match to the calendar.'
220  date_error = .true.
221  endif
222  if ( ymdhms(i_min ) < 0 .or. (int(calendar_min )-1) < ymdhms(i_min ) ) then
223  log_error("CALENDAR_date2daysec",*) 'Inputted minute does not match to the calendar.'
224  date_error = .true.
225  endif
226  if ( ymdhms(i_sec ) < 0 .or. (int(calendar_sec )-1) < ymdhms(i_sec ) ) then
227  log_error("CALENDAR_date2daysec",*) 'Inputted second does not match to the calendar.'
228  date_error = .true.
229  endif
230  if( date_error ) call abort
231 
232  call calendar_ymd2absday( absday, & ! [OUT]
233  ymdhms(i_year), & ! [IN]
234  ymdhms(i_month), & ! [IN]
235  ymdhms(i_day), & ! [IN]
236  offset_year ) ! [IN]
237 
238  call calendar_hms2abssec( abssec, & ! [OUT]
239  ymdhms(i_hour), & ! [IN]
240  ymdhms(i_min), & ! [IN]
241  ymdhms(i_sec), & ! [IN]
242  subsec ) ! [IN]
243 
244  return
245  end subroutine calendar_date2daysec
246 
247  !-----------------------------------------------------------------------------
249  subroutine calendar_daysec2date( &
250  ymdhms, &
251  subsec, &
252  absday, &
253  abssec, &
254  offset_year )
255  implicit none
256 
257  integer, intent(out) :: ymdhms(6)
258  real(dp), intent(out) :: subsec
259  integer, intent(in) :: absday
260  real(dp), intent(in) :: abssec
261  integer, intent(in) :: offset_year
262  !---------------------------------------------------------------------------
263 
264  call calendar_absday2ymd( ymdhms(i_year), & ! [OUT]
265  ymdhms(i_month), & ! [OUT]
266  ymdhms(i_day), & ! [OUT]
267  absday, & ! [IN]
268  offset_year ) ! [IN]
269 
270  call calendar_abssec2hms( ymdhms(i_hour), & ! [OUT]
271  ymdhms(i_min), & ! [OUT]
272  ymdhms(i_sec), & ! [OUT]
273  subsec, & ! [OUT]
274  abssec ) ! [IN]
275 
276  return
277  end subroutine calendar_daysec2date
278 
279  !-----------------------------------------------------------------------------
281  subroutine calendar_ymd2absday( &
282  absday, &
283  gyear, &
284  gmonth, &
285  gday, &
286  oyear )
287  implicit none
288 
289  integer, intent(out) :: absday
290  integer, intent(in) :: gyear
291  integer, intent(in) :: gmonth
292  integer, intent(in) :: gday
293  integer, intent(in) :: oyear
294 
295  integer :: gyear_mod, gmonth_mod
296  integer :: yearday, monthday
297  integer :: m, ileap
298  !---------------------------------------------------------------------------
299 
300  gmonth_mod = mod( gmonth-1, calendar_month ) + 1
301  gyear_mod = gyear + ( gmonth-gmonth_mod ) / calendar_month
302 
303  if ( calendar_360days .OR. calendar_365days .or. calendar_user) then
304  yearday = int( calendar_doi * ( gyear_mod - oyear ) )
305  else
306  yearday = int( calendar_doi * ( gyear_mod - oyear ) ) &
307  + int( real(gyear_mod-1,kind=dp) / 4.0_dp ) &
308  - int( real(gyear_mod-1,kind=dp) / 100.0_dp ) &
309  + int( real(gyear_mod-1,kind=dp) / 400.0_dp ) &
310  - int( real(oyear -1,kind=dp) / 4.0_dp ) &
311  + int( real(oyear -1,kind=dp) / 100.0_dp ) &
312  - int( real(oyear -1,kind=dp) / 400.0_dp )
313  endif
314 
315  ileap = i_nonleapyear
316  if( checkleap(gyear_mod) ) ileap = i_leapyear
317  if( calendar_360days ) ileap = i_360days
318  if( calendar_user ) ileap = i_user
319 
320  monthday = 0
321  do m = 1, gmonth_mod-1
322  monthday = monthday + dayofmonth(m,ileap)
323  enddo
324 
325  absday = yearday + monthday + gday - 1
326 
327  return
328  end subroutine calendar_ymd2absday
329 
330  !-----------------------------------------------------------------------------
332  subroutine calendar_absday2ymd( &
333  gyear, &
334  gmonth, &
335  gday, &
336  absday, &
337  oyear )
338  implicit none
339 
340  integer, intent(out) :: gyear
341  integer, intent(out) :: gmonth
342  integer, intent(out) :: gday
343  integer, intent(in) :: absday
344  integer, intent(in) :: oyear
345 
346  integer :: checkday
347  integer :: i, ileap
348  !---------------------------------------------------------------------------
349 
350  gyear = int( real(absday,kind=dp) / (calendar_doi+1.0_dp) ) + oyear ! first guess
351 
352  do i = 1, 1000
353  call calendar_ymd2absday( checkday, gyear+1, 1, 1, oyear )
354  if( absday < checkday ) exit
355  gyear = gyear + 1
356  enddo
357 
358  ileap = i_nonleapyear
359  if( checkleap(gyear) ) ileap = i_leapyear
360  if( calendar_360days ) ileap = i_360days
361  if( calendar_user ) ileap = i_user
362 
363  gmonth = 1
364  do i = 1, 1000
365  call calendar_ymd2absday( checkday, gyear, gmonth, dayofmonth(gmonth,ileap), oyear )
366  if( absday <= checkday ) exit
367  gmonth = gmonth + 1
368  enddo
369 
370  call calendar_ymd2absday( checkday, gyear, gmonth, 1, oyear )
371  gday = absday - checkday + 1
372 
373  return
374  end subroutine calendar_absday2ymd
375 
376  !-----------------------------------------------------------------------------
378  subroutine calendar_hms2abssec( &
379  abssec, &
380  hour, &
381  minute, &
382  second, &
383  subsec )
384  implicit none
385 
386  real(dp), intent(out) :: abssec
387  integer, intent(in) :: hour
388  integer, intent(in) :: minute
389  integer, intent(in) :: second
390  real(dp), intent(in) :: subsec
391  !---------------------------------------------------------------------------
392 
393  abssec = real(hour, kind=dp) * calendar_min * calendar_sec &
394  + real(minute,kind=dp) * calendar_sec &
395  + real(second,kind=dp) &
396  + subsec
397 
398  return
399  end subroutine calendar_hms2abssec
400 
401  !-----------------------------------------------------------------------------
403  subroutine calendar_abssec2hms( &
404  hour, &
405  minute, &
406  second, &
407  subsec, &
408  abssec )
409  implicit none
410 
411  integer, intent(out) :: hour
412  integer, intent(out) :: minute
413  integer, intent(out) :: second
414  real(dp), intent(out) :: subsec
415  real(dp), intent(in) :: abssec
416 
417  real(dp) :: nsec, nmin, nhour, temp
418  !---------------------------------------------------------------------------
419 
420  nsec = real(int(abssec),kind=dp)
421  subsec = abssec - nsec
422 
423  temp = mod( nsec, calendar_sec )
424  second = int( temp )
425  nmin = ( nsec-temp ) / calendar_sec
426 
427  temp = mod( nmin, calendar_min )
428  minute = int( temp )
429  nhour = ( nmin-temp ) / calendar_min
430 
431  temp = mod( nhour, calendar_hour )
432  hour = int( temp )
433 
434  return
435  end subroutine calendar_abssec2hms
436 
437  !-----------------------------------------------------------------------------
439  subroutine calendar_adjust_daysec( &
440  absday, &
441  abssec )
442  implicit none
443 
444  integer, intent(inout) :: absday
445  real(dp), intent(inout) :: abssec
446 
447  integer :: addday
448  !---------------------------------------------------------------------------
449 
450  addday = int( abssec / ( calendar_hour * calendar_min * calendar_sec ) )
451 
452  absday = absday + addday
453 
454  abssec = abssec - real(addday,kind=dp) * calendar_hour * calendar_min * calendar_sec
455 
456  if ( abssec < 0.0_dp ) then
457  absday = absday - 1
458  abssec = abssec + calendar_hour * calendar_min * calendar_sec
459  endif
460 
461  return
462  end subroutine calendar_adjust_daysec
463 
464  !-----------------------------------------------------------------------------
466  function calendar_combine_daysec( absday, abssec ) result(daysec)
467  implicit none
468 
469  integer, intent(in) :: absday
470  real(dp), intent(in) :: abssec
471  real(dp) :: daysec
472  !---------------------------------------------------------------------------
473 
474  daysec = real(absday,kind=dp) * calendar_sec * calendar_min * calendar_hour &
475  + abssec
476 
477  return
478  end function calendar_combine_daysec
479 
480  !-----------------------------------------------------------------------------
482  subroutine calendar_unit2sec( &
483  second, &
484  value, &
485  unit )
486  use scale_prc, only: &
487  prc_abort
488  implicit none
489 
490  real(dp), intent(out) :: second
491  real(dp), intent(in) :: value
492  character(len=*), intent(in) :: unit
493  !---------------------------------------------------------------------------
494 
495  select case(unit)
496  case('MSEC')
497  second = value * 1.e-3_dp
498  case('SEC', 'seconds')
499  second = value
500  case('MIN')
501  second = value * calendar_sec
502  case('HOUR')
503  second = value * calendar_sec * calendar_min
504  case('DAY')
505  second = value * calendar_sec * calendar_min * calendar_hour
506  case default
507  log_error("CALENDAR_unit2sec",*) 'Unsupported UNIT: ', trim(unit), ', ', value
508  call prc_abort
509  endselect
510 
511  return
512  end subroutine calendar_unit2sec
513 
514  !-----------------------------------------------------------------------------
516  subroutine calendar_sec2unit( &
517  value, &
518  second, &
519  unit )
520  use scale_prc, only: &
521  prc_abort
522  implicit none
523 
524  real(dp), intent(out) :: value
525  real(dp), intent( in) :: second
526  character(len=*), intent( in) :: unit
527  !---------------------------------------------------------------------------
528 
529  select case(trim(unit))
530  case('MSEC', 'msec')
531  value = second / 1.0e-3_dp
532  case('SEC', 'seconds', 'sec', 's')
533  value = second
534  case('MIN', 'mins', 'min')
535  value = second / calendar_sec
536  case('HOUR', 'hours', 'hour', 'h')
537  value = second / (calendar_sec * calendar_min)
538  case('DAY', 'days', 'day')
539  value = second / (calendar_sec * calendar_min * calendar_hour)
540  case default
541  log_error("CALENDAR_sec2unit",*) 'Unsupported UNIT: ', trim(unit), ', ', value
542  call prc_abort
543  endselect
544 
545  end subroutine calendar_sec2unit
546 
547  !-----------------------------------------------------------------------------
549  function calendar_cfunits2sec( cftime, cfunits, offset_year, startdaysec ) result( sec )
550  use scale_prc, only: &
551  prc_abort
552  implicit none
553 
554  real(dp), intent(in) :: cftime
555  character(len=*), intent(in) :: cfunits
556  integer, intent(in) :: offset_year
557  real(dp), intent(in), optional :: startdaysec
558  real(dp) :: sec
559 
560  character(len=H_MID) :: tunit
561  character(len=H_MID) :: buf
562 
563  integer :: date(6)
564  integer :: day
565  real(dp) :: sec0
566 
567  integer :: l
568 
569  intrinsic index
570  !---------------------------------------------------------------------------
571 
572  l = index( cfunits, " since " )
573  if ( l > 1 ) then ! untis is under the CF convension
574  tunit = cfunits(1:l-1)
575  buf = cfunits(l+7:)
576 
577  l = index(buf,"-")
578  if ( l /= 5 ) then
579  log_error("CALENDAR_CFunits2sec",*) 'units for time is invalid (year)'
580  log_error_cont(*) trim(cfunits)
581  log_error_cont(*) trim(buf)
582  call prc_abort
583  end if
584  read(buf(1:4),*) date(1) ! year
585  buf = buf(6:)
586 
587  l = index(buf,"-")
588  if ( l /= 3 ) then
589  log_error("CALENDAR_CFunits2sec",*) 'units for time is invalid (month)'
590  log_error_cont(*) trim(cfunits)
591  log_error_cont(*) trim(buf)
592  call prc_abort
593  end if
594  read(buf(1:2),*) date(2) ! month
595  buf = buf(4:)
596 
597  l = index(buf," ")
598  if ( l /= 3 ) then
599  log_error("CALENDAR_CFunits2sec",*) 'units for time is invalid (day)'
600  log_error_cont(*) trim(cfunits)
601  log_error_cont(*) trim(buf)
602  call prc_abort
603  end if
604  read(buf(1:2),*) date(3) ! day
605  buf = buf(4:)
606 
607  l = index(buf,":")
608  if ( l /= 3 ) then
609  log_error("CALENDAR_CFunits2sec",*) 'units for time is invalid (hour)'
610  log_error_cont(*) trim(cfunits)
611  log_error_cont(*) trim(buf)
612  call prc_abort
613  end if
614  read(buf(1:2),*) date(4) ! hour
615  buf = buf(4:)
616 
617  l = index(buf,":")
618  if ( l /= 3 ) then
619  log_error("CALENDAR_CFunits2sec",*) 'units for time is invalid (min)'
620  log_error_cont(*) trim(cfunits)
621  log_error_cont(*) trim(buf)
622  call prc_abort
623  end if
624  read(buf(1:2),*) date(5) ! min
625  buf = buf(4:)
626 
627  if ( len_trim(buf) /= 2 ) then
628  log_error("CALENDAR_CFunits2sec",*) 'units for time is invalid (sec)'
629  log_error_cont(*) trim(cfunits)
630  log_error_cont(*) trim(buf)
631  log_error_cont(*) len_trim(buf)
632  call prc_abort
633  end if
634  read(buf(1:2),*) date(6) ! sec
635 
636  call calendar_date2daysec( day, & ! (out)
637  sec0, & ! (out)
638  date(:), & ! (in)
639  0.0_dp, & ! (in)
640  offset_year ) ! (in)
641 
642  sec0 = calendar_combine_daysec( day, sec0 )
643  else
644  tunit = cfunits
645  if ( present(startdaysec) ) then
646  sec0 = startdaysec
647  else
648  sec0 = 0.0_dp
649  end if
650  end if
651 
652  call calendar_unit2sec( sec, cftime, tunit )
653 
654  sec = sec0 + sec
655 
656  return
657  end function calendar_cfunits2sec
658 
659  !-----------------------------------------------------------------------------
661  subroutine calendar_date2char( &
662  chardate, &
663  ymdhms, &
664  subsec )
665  implicit none
666 
667  character(len=27), intent(out) :: chardate
668  integer, intent(in) :: ymdhms(6)
669  real(dp), intent(in) :: subsec
670 
671  character(len=4) :: seclen
672  character(len=4) :: minlen
673  character(len=4) :: hourlen
674  character(len=4) :: daylen
675  character(len=4) :: monthlen
676 
677 
678  !---------------------------------------------------------------------------
679  if ( calendar_user) then
680  write(daylen, '(A1,I1.1,A1,I1.1)') 'I', int(log10(real(maxval(calendar_user_defined))))+1, &
681  '.', int(log10(real(maxval(calendar_user_defined))))+1
682  if( calendar_month < 10 ) then
683  write(monthlen, '(A4)') 'I1.1'
684  else
685  write(monthlen, '(A4)') 'I2.2'
686  endif
687  else
688  write(daylen, '(A4)') 'I2.2'
689  write(monthlen, '(A4)') 'I2.2'
690  endif
691 
692  write(seclen, '(A1,I1.1,A1,I1.1)') 'I', int(log10(max(calendar_sec -1.0_dp, 1.0_dp)))+1, &
693  '.', int(log10(max(calendar_sec -1.0_dp, 1.0_dp)))+1
694  write(minlen, '(A1,I1.1,A1,I1.1)') 'I', int(log10(max(calendar_min -1.0_dp, 1.0_dp)))+1, &
695  '.', int(log10(max(calendar_min -1.0_dp, 1.0_dp)))+1
696  write(hourlen,'(A1,I1.1,A1,I1.1)') 'I', int(log10(max(calendar_hour-1.0_dp, 1.0_dp)))+1, &
697  '.', int(log10(max(calendar_hour-1.0_dp, 1.0_dp)))+1
698 
699 ! write(chardate,'(I4.4,A1,I2.2,A1,I2.2,A1,I2.2,A1,I2.2,A1,I2.2,A2,F6.3)') &
700  write(chardate,'(I4.4,A1,'//monthlen//',A1,'//daylen//',A1,'//hourlen//',A1,'//minlen//',A1,'//seclen//',A2,F6.3)') &
701  ymdhms(1),'/',ymdhms(2),'/',ymdhms(3),' ', &
702  ymdhms(4),':',ymdhms(5),':',ymdhms(6),' +', &
703  subsec
704 
705  return
706  end subroutine calendar_date2char
707 
708  !-----------------------------------------------------------------------------
711  function checkleap( iyear )
712  implicit none
713 
714  integer, intent(in) :: iyear
715  logical :: checkleap
716 
717  integer :: check4, check100, check400
718  !---------------------------------------------------------------------------
719 
720  check4 = mod(iyear,4 )
721  check100 = mod(iyear,100)
722  check400 = mod(iyear,400)
723 
724  checkleap = .false.
725  if( check4 == 0 ) checkleap = .true.
726  if( check100 == 0 ) checkleap = .false.
727  if( check400 == 0 ) checkleap = .true.
728 
729  if( calendar_360days ) checkleap = .false.
730  if( calendar_365days ) checkleap = .false.
731  if( calendar_user ) checkleap = .false.
732 
733  end function checkleap
734 
735  !-----------------------------------------------------------------------------
737  subroutine calendar_ymdhms2nd( &
738  nd, &
739  ymdhms, &
740  oyear )
741  implicit none
742 
743  real(dp), intent(out) :: nd
744  integer, intent(in) :: ymdhms(6)
745  integer, intent(in) :: oyear
746 
747  integer :: absday, absday_jan1
748  !---------------------------------------------------------------------------
749 
750  call calendar_ymd2absday( absday, & ! [OUT]
751  ymdhms(i_year), & ! [IN]
752  ymdhms(i_month), & ! [IN]
753  ymdhms(i_day), & ! [IN]
754  oyear ) ! [IN]
755 
756  call calendar_ymd2absday( absday_jan1, & ! [OUT]
757  ymdhms(i_year), & ! [IN]
758  1, & ! [IN]
759  1, & ! [IN]
760  oyear ) ! [IN]
761 
762  nd = absday - absday_jan1 + 1.0_dp
763 
764  return
765  end subroutine calendar_ymdhms2nd
766 
767  !-----------------------------------------------------------------------------
769  subroutine calendar_ymdhms2mjd( &
770  mjd, &
771  ymdhms, &
772  oyear )
773  implicit none
774 
775  real(dp), intent(out) :: mjd
776  integer, intent(in) :: ymdhms(6)
777  integer, intent(in) :: oyear
778 
779  integer :: y, m, mjd_day
780  !---------------------------------------------------------------------------
781 
782  if ( ymdhms(i_month) == 1 &
783  .OR. ymdhms(i_month) == 2 ) then
784  y = ymdhms(i_year) - 1
785  m = ymdhms(i_month) + 2
786  else
787  y = ymdhms(i_year)
788  m = ymdhms(i_month)
789  endif
790 
791  mjd_day = int( 365.25_dp * y ) & ! year
792  + int( y/400.0_dp ) - int( y/100.0_dp ) & ! leap year
793  + int( 30.59_dp * m-2 ) & ! month
794  + ymdhms(i_day) & ! day
795  + 678912 ! constant
796 
797  mjd = real(mjd_day,kind=dp) & ! day
798  + ymdhms(i_hour) / (calendar_hour ) & ! hour
799  + ymdhms(i_min) / (calendar_hour*calendar_min ) & ! min
800  + ymdhms(i_sec) / (calendar_hour*calendar_min*calendar_sec) ! sec
801 
802  return
803  end subroutine calendar_ymdhms2mjd
804 
805  subroutine calendar_get_name(name)
806  character(len=*), intent(out) :: name
807 
808  if ( calendar_360days ) then
809  name = "360_day"
810  elseif( calendar_365days ) then
811  name = "365_day"
812  elseif( calendar_user ) then
813  name = "USER_DEFINED"
814  else
815  name = "gregorian"
816  endif
817 
818  return
819  end subroutine calendar_get_name
820 
821 end module scale_calendar
scale_prc::prc_abort
subroutine, public prc_abort
Abort Process.
Definition: scale_prc.F90:350
scale_calendar::i_min
integer, parameter, public i_min
[index] minute
Definition: scale_calendar.F90:49
scale_calendar::calendar_daysec2date
subroutine, public calendar_daysec2date(ymdhms, subsec, absday, abssec, offset_year)
Convert from gregorian date to absolute day/second.
Definition: scale_calendar.F90:255
scale_calendar::calendar_get_name
subroutine, public calendar_get_name(name)
Definition: scale_calendar.F90:806
scale_calendar::calendar_combine_daysec
real(dp) function, public calendar_combine_daysec(absday, abssec)
Combine day and second.
Definition: scale_calendar.F90:467
scale_precision
module PRECISION
Definition: scale_precision.F90:14
scale_calendar::calendar_sec2unit
subroutine, public calendar_sec2unit(value, second, unit)
Convert several second to specified unit.
Definition: scale_calendar.F90:520
scale_calendar::calendar_getdayofyear
subroutine, public calendar_getdayofyear(DayOfYear, iyear)
Get day of year.
Definition: scale_calendar.F90:172
scale_calendar::calendar_hms2abssec
subroutine, public calendar_hms2abssec(abssec, hour, minute, second, subsec)
Hour, minute, second, subsecond -> absolute second.
Definition: scale_calendar.F90:384
scale_calendar
module CALENDAR
Definition: scale_calendar.F90:13
scale_prc
module PROCESS
Definition: scale_prc.F90:11
scale_io
module STDIO
Definition: scale_io.F90:10
scale_calendar::calendar_min
real(dp), public calendar_min
minutes of hour
Definition: scale_calendar.F90:54
scale_calendar::calendar_ymd2absday
subroutine, public calendar_ymd2absday(absday, gyear, gmonth, gday, oyear)
Convert from gregorian date to absolute day, DAY 0 is AD1/1/1.
Definition: scale_calendar.F90:287
scale_calendar::i_hour
integer, parameter, public i_hour
[index] hour
Definition: scale_calendar.F90:48
scale_calendar::calendar_date2daysec
subroutine, public calendar_date2daysec(absday, abssec, ymdhms, subsec, offset_year)
Convert from gregorian date to absolute day/second.
Definition: scale_calendar.F90:192
scale_calendar::calendar_adjust_daysec
subroutine, public calendar_adjust_daysec(absday, abssec)
Adjust day and second.
Definition: scale_calendar.F90:442
scale_calendar::calendar_sec
real(dp), public calendar_sec
seconds of minute
Definition: scale_calendar.F90:55
scale_precision::dp
integer, parameter, public dp
Definition: scale_precision.F90:32
scale_calendar::calendar_cfunits2sec
real(dp) function, public calendar_cfunits2sec(cftime, cfunits, offset_year, startdaysec)
Convert time in units of the CF convention to second.
Definition: scale_calendar.F90:550
scale_calendar::i_month
integer, parameter, public i_month
[index] month
Definition: scale_calendar.F90:46
scale_calendar::calendar_setup
subroutine, public calendar_setup
Setup.
Definition: scale_calendar.F90:95
scale_calendar::calendar_hour
real(dp), public calendar_hour
hours of day
Definition: scale_calendar.F90:53
scale_calendar::i_year
integer, parameter, public i_year
[index] year
Definition: scale_calendar.F90:45
scale_calendar::i_day
integer, parameter, public i_day
[index] day
Definition: scale_calendar.F90:47
scale_calendar::calendar_doi
real(dp), public calendar_doi
days of year
Definition: scale_calendar.F90:52
scale_io::io_fid_conf
integer, public io_fid_conf
Config file ID.
Definition: scale_io.F90:57
scale_calendar::calendar_date2char
subroutine, public calendar_date2char(chardate, ymdhms, subsec)
Convert from gregorian date to absolute day/second.
Definition: scale_calendar.F90:665
scale_calendar::i_sec
integer, parameter, public i_sec
[index] second
Definition: scale_calendar.F90:50
scale_calendar::calendar_unit2sec
subroutine, public calendar_unit2sec(second, value, unit)
Convert several units to second.
Definition: scale_calendar.F90:486