Date and Time

Modern Fortran features some basic time routines. On POSIX-compliant systems, the ISO C binding interface allows us to use additional timing routines defined in the C standard library (libc).

Current Date and Time

The routine date_and_time(date, time, zone, values) returns date and time information from the real-time system clock.

call date_and_time([date][, time][, zone][, values])
Argument Type Description
date character(len=8) date in form ccyymmdd
time character(len=10) time in form hhmmss.sss
zone character(len=5) zone in form (+-)hhmm, representing the difference with respect to UTC
values integer(8) array with year (1), month (2), day of month (3), time difference with UTC in minutes (4), hour (5), minutes (6), seconds (7), and milliseconds (8)

The following example outputs the current date and time, as well as the .beat time:

! datetime.f90
program main
    implicit none
    integer :: dt(8)
    real    :: beats

    call date_and_time(values=dt)
    print '(i4, 5(a, i2.2))', dt(1), '/', dt(2), '/', dt(3), ' ', &
                              dt(5), ':', dt(6), ':', dt(7)
    beats = (dt(7) + ((dt(6) - dt(4) + 60) * 60) + (dt(5) * 3600)) / 86.4
    print '("Beats: @", f0.2)', beats
end program main

Sleep

The intrinsic sleep() routine pauses the program for a given number of seconds:

! time.f90
program main
    ! Sleep for 5 seconds ...
    call sleep(5)
end program main

In order to sleep for less than a second, one can write an interface to the libc routine usleep(), which pauses for a given interval measured in microseconds:

! posix_sleep.f90
program main
    implicit none
    integer :: i
    integer :: t = 500000 ! 500 milliseconds

    interface
        subroutine usleep(useconds) bind(c)
            use, intrinsic :: iso_c_binding, only: c_int32_t
            implicit none
            integer(c_int32_t), value :: useconds
        end subroutine
    end interface

    do i = 1, 10
        print '(a)', 'zzz ...'
        call microsleep(t)
    end do

contains

    subroutine microsleep(useconds)
        !! Wrapper for `usleep()` that converts integer to c_int32_t.
        use, intrinsic :: iso_c_binding, only: c_int32_t
        implicit none
        integer :: useconds
        call usleep(int(useconds, kind=c_int32_t))
    end subroutine microsleep
end program main

The wrapper routine microsleep() does the type convertion from integer to c_int32_t.

CPU Time

The intrinsic Fortran routine cpu_time() returns the ellapsed CPU time in microseconds.

Mandelbrot set in Fortran
Fig. 1: The example Mandelbrot program

The example measures the time required to compute the Mandelbrot set (fig. 1):

! mandelbrot.f90
program main
    implicit none
    integer, parameter :: width     = 80
    integer, parameter :: height    = 40
    integer, parameter :: max_iter  = 90
    real,    parameter :: threshold = 2.0
    integer            :: x, y
    real               :: re, im
    real               :: t1, t2

    call cpu_time(t1)

    do y = 0, height
        im = -1.5 + real(y) * 3.0 / real(height)

        do x = 0, width
            re = -2.0 + real(x) * 3.0 / real(width)

            if (mandelbrot(cmplx(re, im), max_iter, threshold) < 10) then
                write (*, '(a)', advance='no') ' '
            else
                write (*, '(a)', advance='no') '*'
            end if
        end do

        write (*, '(a)')
    end do

    call cpu_time(t2)
    print '("Time: ", f8.6, " seconds")', t2 - t1

contains

    function mandelbrot(c, max_iter, threshold)
        !! Calculates Mandelbrot set.
        complex, intent(in) :: c
        integer, intent(in) :: max_iter
        real,    intent(in) :: threshold
        integer             :: mandelbrot
        complex             :: z

        z = (0.0, 0.0)

        do mandelbrot = 0, max_iter
            z = z**2 + c

            if (abs(z) > threshold) &
                exit
        end do
    end function mandelbrot
end program main