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 integer, parameter, public i_month
[index] month
subroutine, public calendar_unit2sec(second, value, unit)
Convert several units to second.
integer, parameter, public i_year
[index] year
real(dp) function, public calendar_combine_daysec(absday, abssec)
Combine day and second.
subroutine, public calendar_ymd2absday(absday, gyear, gmonth, gday, oyear)
Convert from gregorian date to absolute day, DAY 0 is AD1/1/1.
subroutine, public calendar_date2char(chardate, ymdhms, subsec)
Convert from gregorian date to absolute day/second.
integer, public io_fid_conf
Config file ID.
subroutine, public calendar_adjust_daysec(absday, abssec)
Adjust day and second.
subroutine, public calendar_setup
Setup.
subroutine, public calendar_get_name(name)
real(dp) function, public calendar_cfunits2sec(cftime, cfunits, offset_year, startdaysec)
Convert time in units of the CF convention to second.
integer, parameter, public i_min
[index] minute
subroutine, public calendar_sec2unit(value, second, unit)
Convert several second to specified unit.
integer, parameter, public i_sec
[index] second
subroutine, public prc_abort
Abort Process.
integer, parameter, public i_hour
[index] hour
integer, parameter, public i_day
[index] day
subroutine, public calendar_daysec2date(ymdhms, subsec, absday, abssec, offset_year)
Convert from gregorian date to absolute day/second.
subroutine, public calendar_getdayofyear(DayOfYear, iyear)
Get day of year.
subroutine, public calendar_hms2abssec(abssec, hour, minute, second, subsec)
Hour, minute, second, subsecond -> absolute second.
integer, parameter, public dp
subroutine, public calendar_date2daysec(absday, abssec, ymdhms, subsec, offset_year)
Convert from gregorian date to absolute day/second.