days_from_civil Function

private pure function days_from_civil(y_in, m, d) result(days)

Days from 1970-01-01 to the given proleptic Gregorian date.

Howard Hinnant’s days_from_civil, which is exact for every date in the int64 range and uses only integer operations. The year is shifted so that the era begins on 1 March, which is what removes the leap-day special case from the month arithmetic.

Arguments

Type IntentOptional Attributes Name
integer(kind=int64), intent(in) :: y_in
integer(kind=int64), intent(in) :: m
integer(kind=int64), intent(in) :: d

Return Value integer(kind=int64)


Called by

proc~~days_from_civil~~CalledByGraph proc~days_from_civil days_from_civil proc~unix_time_ms unix_time_ms proc~unix_time_ms->proc~days_from_civil proc~now_utc now_utc proc~now_utc->proc~unix_time_ms

Variables

Type Visibility Attributes Name Initial
integer(kind=int64), private :: doe
integer(kind=int64), private :: doy
integer(kind=int64), private :: era
integer(kind=int64), private :: y
integer(kind=int64), private :: yoe

Source Code

   pure function days_from_civil(y_in, m, d) result(days)
      !! Days from 1970-01-01 to the given proleptic Gregorian date.
      !!
      !! Howard Hinnant's `days_from_civil`, which is exact for every date in
      !! the int64 range and uses only integer operations. The year is shifted
      !! so that the era begins on 1 March, which is what removes the leap-day
      !! special case from the month arithmetic.
      integer(int64), intent(in) :: y_in
      integer(int64), intent(in) :: m
      integer(int64), intent(in) :: d
      integer(int64) :: days

      integer(int64) :: y, era, yoe, doy, doe

      y = y_in
      if (m <= 2_int64) y = y - 1_int64

      if (y >= 0_int64) then
         era = y/400_int64
      else
         era = (y - 399_int64)/400_int64
      end if

      yoe = y - era*400_int64                                  ! [0, 399]
      if (m > 2_int64) then
         doy = (153_int64*(m - 3_int64) + 2_int64)/5_int64 + d - 1_int64
      else
         doy = (153_int64*(m + 9_int64) + 2_int64)/5_int64 + d - 1_int64
      end if
      doe = yoe*365_int64 + yoe/4_int64 - yoe/100_int64 + doy  ! [0, 146096]

      days = era*146097_int64 + doe - DAYS_EPOCH_SHIFT
   end function days_from_civil