get_utc_since_1582 Function

private 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

Arguments

TypeIntentOptionalAttributesName
integer, intent(in), dimension(8):: values

Return Value integer(kind=INT64)


Called by

proc~~get_utc_since_1582~~CalledByGraph proc~get_utc_since_1582 get_utc_since_1582 proc~generate_uuid generate_uuid proc~generate_uuid->proc~get_utc_since_1582

Contents

Source Code


Source Code

    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