45 integer,
public,
parameter ::
i_year = 1
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
56 private :: calendar_absday2ymd
57 private :: calendar_abssec2hms
58 private :: calendar_ymdhms2nd
59 private :: calendar_ymdhms2mjd
66 logical,
private :: calendar_360days = .false.
67 logical,
private :: calendar_365days = .false.
69 real(
dp),
private :: calendar_doi = 365.0_dp
70 real(
dp),
private :: calendar_hour = 24.0_dp
71 real(
dp),
private :: calendar_min = 60.0_dp
72 real(
dp),
private :: calendar_sec = 60.0_dp
74 integer,
private,
parameter :: i_nonleapyear = 1
75 integer,
private,
parameter :: i_leapyear = 2
76 integer,
private,
parameter :: i_360days = 3
77 integer,
private :: dayofmonth(12,3)
78 data dayofmonth / 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, &
79 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31, &
80 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30, 30 /
82 logical,
private :: debug = .false.
93 namelist / param_calendar / &
102 log_info(
"CALENDAR_setup",*)
'Setup'
108 log_info(
"CALENDAR_setup",*)
'Not found namelist. Default used.'
109 elseif( ierr > 0 )
then
110 log_error(
"CALENDAR_setup",*)
'Not appropriate names in namelist PARAM_CALENDAR. Check!'
113 log_nml(param_calendar)
115 if ( calendar_360days )
then
116 calendar_doi = 360.0_dp
117 elseif( calendar_365days )
then
118 calendar_doi = 365.0_dp
122 log_info(
"CALENDAR_setup",*)
'Calendar settings'
123 if ( calendar_360days )
then
124 log_info_cont(*)
'DayOfYear = 360 : ideal setting'
125 elseif( calendar_365days )
then
126 log_info_cont(*)
'DayOfYear = 365 : ideal setting'
128 log_info_cont(*)
'DayOfYear = 365 or 366 : Gregorian calendar'
141 real(
dp),
intent(out) :: dayofyear
142 integer,
intent(in) :: iyear
145 dayofyear = calendar_doi
146 if( checkleap(iyear) ) dayofyear = calendar_doi + 1.0_dp
161 integer,
intent(out) :: absday
162 real(
dp),
intent(out) :: abssec
163 integer,
intent(in) :: ymdhms(6)
164 real(
dp),
intent(in) :: subsec
165 integer,
intent(in) :: offset_year
193 integer,
intent(out) :: ymdhms(6)
194 real(
dp),
intent(out) :: subsec
195 integer,
intent(in) :: absday
196 real(
dp),
intent(in) :: abssec
197 integer,
intent(in) :: offset_year
200 call calendar_absday2ymd( ymdhms(
i_year), &
206 call calendar_abssec2hms( ymdhms(
i_hour), &
225 integer,
intent(out) :: absday
226 integer,
intent(in) :: gyear
227 integer,
intent(in) :: gmonth
228 integer,
intent(in) :: gday
229 integer,
intent(in) :: oyear
231 integer :: gyear_mod, gmonth_mod
232 integer :: yearday, monthday
236 gmonth_mod = mod( gmonth-1, 12 ) + 1
237 gyear_mod = gyear + ( gmonth-gmonth_mod ) / 12
239 if ( calendar_360days .OR. calendar_365days )
then
240 yearday = int( calendar_doi * ( gyear_mod - oyear ) )
242 yearday = int( calendar_doi * ( gyear_mod - oyear ) ) &
243 + int( real(gyear_mod-1,kind=
dp) / 4.0_dp ) &
244 - int( real(gyear_mod-1,kind=
dp) / 100.0_dp ) &
245 + int( real(gyear_mod-1,kind=
dp) / 400.0_dp ) &
246 - int( real(oyear -1,kind=
dp) / 4.0_dp ) &
247 + int( real(oyear -1,kind=
dp) / 100.0_dp ) &
248 - int( real(oyear -1,kind=
dp) / 400.0_dp )
251 ileap = i_nonleapyear
252 if( checkleap(gyear_mod) ) ileap = i_leapyear
253 if( calendar_360days ) ileap = i_360days
256 do m = 1, gmonth_mod-1
257 monthday = monthday + dayofmonth(m,ileap)
260 absday = yearday + monthday + gday - 1
267 subroutine calendar_absday2ymd( &
275 integer,
intent(out) :: gyear
276 integer,
intent(out) :: gmonth
277 integer,
intent(out) :: gday
278 integer,
intent(in) :: absday
279 integer,
intent(in) :: oyear
285 if ( calendar_360days )
then
286 gyear = int( real(absday,kind=
dp) / 361.0_dp ) + oyear
288 gyear = int( real(absday,kind=
dp) / 366.0_dp ) + oyear
293 if( absday < checkday )
exit
297 ileap = i_nonleapyear
298 if( checkleap(gyear) ) ileap = i_leapyear
299 if( calendar_360days ) ileap = i_360days
304 if( absday <= checkday )
exit
309 gday = absday - checkday + 1
312 end subroutine calendar_absday2ymd
324 real(
dp),
intent(out) :: abssec
325 integer,
intent(in) :: hour
326 integer,
intent(in) :: minute
327 integer,
intent(in) :: second
328 real(
dp),
intent(in) :: subsec
331 abssec = real(hour, kind=
dp) * calendar_min * calendar_sec &
332 + real(minute,kind=
dp) * calendar_sec &
333 + real(second,kind=
dp) &
341 subroutine calendar_abssec2hms( &
349 integer,
intent(out) :: hour
350 integer,
intent(out) :: minute
351 integer,
intent(out) :: second
352 real(
dp),
intent(out) :: subsec
353 real(
dp),
intent(in) :: abssec
355 real(
dp) :: nsec, nmin, nhour, temp
358 nsec = real(int(abssec),kind=
dp)
359 subsec = abssec - nsec
361 temp = mod( nsec, calendar_sec )
363 nmin = ( nsec-temp ) / calendar_sec
365 temp = mod( nmin, calendar_min )
367 nhour = ( nmin-temp ) / calendar_min
369 temp = mod( nhour, calendar_hour )
373 end subroutine calendar_abssec2hms
382 integer,
intent(inout) :: absday
383 real(
dp),
intent(inout) :: abssec
388 addday = int( abssec / ( calendar_hour * calendar_min * calendar_sec ) )
390 absday = absday + addday
392 abssec = abssec - real(addday,kind=
dp) * calendar_hour * calendar_min * calendar_sec
394 if ( abssec < 0.0_dp )
then
396 abssec = abssec + calendar_hour * calendar_min * calendar_sec
407 integer,
intent(in) :: absday
408 real(
dp),
intent(in) :: abssec
412 daysec = real(absday,kind=
dp) * calendar_sec * calendar_min * calendar_hour &
428 real(
dp),
intent(out) :: second
429 real(
dp),
intent(in) ::
value
430 character(len=*),
intent(in) :: unit
435 second =
value * 1.e-3_dp
436 case(
'SEC',
'seconds')
439 second =
value * calendar_sec
441 second =
value * calendar_sec * calendar_min
443 second =
value * calendar_sec * calendar_min * calendar_hour
445 log_error(
"CALENDAR_unit2sec",*)
'Unsupported UNIT: ', trim(unit),
', ',
value
462 real(
dp),
intent(out) :: value
463 real(
dp),
intent( in) :: second
464 character(len=*),
intent( in) :: unit
467 select case(trim(unit))
469 value = second / 1.0e-3_dp
470 case(
'SEC',
'seconds',
'sec',
's')
472 case(
'MIN',
'mins',
'min')
473 value = second / calendar_sec
474 case(
'HOUR',
'hours',
'hour',
'h')
475 value = second / (calendar_sec * calendar_min)
476 case(
'DAY',
'days',
'day')
477 value = second / (calendar_sec * calendar_min * calendar_hour)
479 log_error(
"CALENDAR_sec2unit",*)
'Unsupported UNIT: ', trim(unit),
', ',
value
492 real(
dp),
intent(in) :: cftime
493 character(len=*),
intent(in) :: cfunits
494 integer,
intent(in) :: offset_year
495 real(
dp),
intent(in),
optional :: startdaysec
498 character(len=H_MID) :: tunit
499 character(len=H_MID) :: buf
510 l = index( cfunits,
" since " )
512 tunit = cfunits(1:l-1)
517 log_error(
"CALENDAR_CFunits2sec",*)
'units for time is invalid (year)'
518 log_error_cont(*) trim(cfunits)
519 log_error_cont(*) trim(buf)
522 read(buf(1:4),*) date(1)
527 log_error(
"CALENDAR_CFunits2sec",*)
'units for time is invalid (month)'
528 log_error_cont(*) trim(cfunits)
529 log_error_cont(*) trim(buf)
532 read(buf(1:2),*) date(2)
537 log_error(
"CALENDAR_CFunits2sec",*)
'units for time is invalid (day)'
538 log_error_cont(*) trim(cfunits)
539 log_error_cont(*) trim(buf)
542 read(buf(1:2),*) date(3)
547 log_error(
"CALENDAR_CFunits2sec",*)
'units for time is invalid (hour)'
548 log_error_cont(*) trim(cfunits)
549 log_error_cont(*) trim(buf)
552 read(buf(1:2),*) date(4)
557 log_error(
"CALENDAR_CFunits2sec",*)
'units for time is invalid (min)'
558 log_error_cont(*) trim(cfunits)
559 log_error_cont(*) trim(buf)
562 read(buf(1:2),*) date(5)
565 if ( len_trim(buf) /= 2 )
then
566 log_error(
"CALENDAR_CFunits2sec",*)
'units for time is invalid (sec)'
567 log_error_cont(*) trim(cfunits)
568 log_error_cont(*) trim(buf)
569 log_error_cont(*) len_trim(buf)
572 read(buf(1:2),*) date(6)
583 if (
present(startdaysec) )
then
605 character(len=27),
intent(out) :: chardate
606 integer,
intent(in) :: ymdhms(6)
607 real(
dp),
intent(in) :: subsec
610 write(chardate,
'(I4.4,A1,I2.2,A1,I2.2,A1,I2.2,A1,I2.2,A1,I2.2,A2,F6.3)') &
611 ymdhms(1),
'/',ymdhms(2),
'/',ymdhms(3),
' ', &
612 ymdhms(4),
':',ymdhms(5),
':',ymdhms(6),
' +', &
621 function checkleap( iyear )
624 integer,
intent(in) :: iyear
627 integer :: check4, check100, check400
630 check4 = mod(iyear,4 )
631 check100 = mod(iyear,100)
632 check400 = mod(iyear,400)
635 if( check4 == 0 ) checkleap = .true.
636 if( check100 == 0 ) checkleap = .false.
637 if( check400 == 0 ) checkleap = .true.
639 if( calendar_360days ) checkleap = .false.
640 if( calendar_365days ) checkleap = .false.
642 end function checkleap
646 subroutine calendar_ymdhms2nd( &
652 real(
dp),
intent(out) :: nd
653 integer,
intent(in) :: ymdhms(6)
654 integer,
intent(in) :: oyear
656 integer :: absday, absday_jan1
671 nd = absday - absday_jan1 + 1.0_dp
674 end subroutine calendar_ymdhms2nd
678 subroutine calendar_ymdhms2mjd( &
684 real(
dp),
intent(out) :: mjd
685 integer,
intent(in) :: ymdhms(6)
686 integer,
intent(in) :: oyear
688 integer :: y, m, mjd_day
692 .OR. ymdhms(
i_month) == 2 )
then
700 mjd_day = int( 365.25_dp * y ) &
701 + int( y/400.0_dp ) - int( y/100.0_dp ) &
702 + int( 30.59_dp * m-2 ) &
706 mjd = real(mjd_day,kind=
dp) &
707 + ymdhms(
i_hour) / 24.0_dp &
708 + ymdhms(
i_min) / 1440.0_dp &
709 + ymdhms(
i_sec) / 86400.0_dp
712 end subroutine calendar_ymdhms2mjd
715 character(len=*),
intent(out) :: name
717 if ( calendar_360days )
then
719 elseif( calendar_365days )
then