This subroutine is a little broken. It only works for times after 1/1/2006 and takes no account of any future leapseconds. It ought to serve regardless.
It returns the number of 100-ns intervals since 1582-10-15-00-00-00
| Type | Intent | Optional | Attributes | Name | ||
|---|---|---|---|---|---|---|
| integer, | intent(in), | dimension(8) | :: | values |
function get_utc_since_1582(values) result(ns)
!! This subroutine is a little broken. It only works
!! for times after 1/1/2006 and takes no account
!! of any future leapseconds. It ought to serve regardless.
!!
!! It returns the number of 100-ns intervals since 1582-10-15-00-00-00
integer, dimension(8), intent(in) :: values
integer(kind=INT64) :: ns
integer :: days
integer :: years
integer, parameter :: days_in_normal_year(12) = &
[31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31]
ns = 23_INT64 * 1000_INT64 * 1000_INT64 * 10_INT64 ! 23 leap seconds until 24:00:00 31/12/2005
! A count of the 100-nanosecond intervals since the
! beginning of the day.
ns = ns &
! milliseconds
+ int(values(8), INT64) * 10_INT64 * 1000_INT64 &
! seconds
+ int(values(7), INT64) * 10_INT64 * 1000_INT64 * 1000_INT64 &
! minutes (with timezone adjustment)
+ int(values(6) + values(4), INT64) * 10_INT64 * 1000_INT64 * 1000_INT64 * 60_INT64 &
! hours
+ int(values(5), INT64) * 10_INT64 * 1000_INT64 * 1000_INT64 * 60_INT64 * 60_INT64
! Number of days this year:
days = sum(days_in_normal_year(:values(2)-1))
days = days + values(3) - 1 !add days in current month
if (values(2)>2 .and. isLeapYear(values(1))) then
days = days + 1
endif
!That's all the time since the turn of this year
days = days + 78 ! From the start of 15th Oct to the end of 31st Dec in 1582
!That's the additional time before the turn of the year 1583
days = days + 102 ! 102 leap years from 1584 to 2000 inclusive
! That's all the intercalated days until 2000
years = values(1) - 2000 - 1 ! years since 2000 - not including this year
days = days + years/4 - years/100 + years/400 !Add extra leap days to this total:
! That's all out intercalated days - remaining years are all 365 days long.
years = years + 418 ! Add the years from 1583-2000 inclusive back on.
! Multiply by number of time units in one day & add to today's total.
ns = ns + 864000000000_INT64 * (int(days,INT64) + 365_INT64 * int(years,INT64))
contains
function isLeapYear(y) result(p)
integer, intent(in) :: y
logical :: p
p = (mod(y,4)==0 .and. .not.mod(y,100)==0 .or. mod(y,400)==0)
end function isLeapYear
end function get_utc_since_1582