Time in Fortran

Our first program will demonstrate various time-related operations in Fortran. Here’s the full source code:

program time_example
    use, intrinsic :: iso_fortran_env
    use, intrinsic :: iso_c_binding
    implicit none

    type(c_ptr) :: time_ptr
    integer(kind=c_int64_t) :: now, then
    integer :: year, month, day, hour, minute, second
    real(kind=c_double) :: diff_seconds

    ! Get the current time
    call system_clock(now)
    print *, "Current time:", now

    ! Create a specific time
    call c_f_pointer(c_loc(then), time_ptr)
    call tm_set(time_ptr, 2009, 11, 17, 20, 34, 58)
    print *, "Specified time:", then

    ! Extract components of the time
    call tm_get(time_ptr, year, month, day, hour, minute, second)
    print *, "Year:", year
    print *, "Month:", month
    print *, "Day:", day
    print *, "Hour:", hour
    print *, "Minute:", minute
    print *, "Second:", second

    ! Compare times
    print *, "Is specified time before current time?", then < now
    print *, "Is specified time after current time?", then > now
    print *, "Are times equal?", then == now

    ! Calculate time difference
    diff_seconds = real(now - then, kind=c_double) / real(count_rate(), kind=c_double)
    print *, "Time difference (seconds):", diff_seconds

    ! Add time
    then = then + int(diff_seconds * count_rate(), kind=c_int64_t)
    print *, "Time after adding difference:", then

contains

    subroutine tm_set(tm, year, month, day, hour, minute, second)
        use, intrinsic :: iso_c_binding
        implicit none
        type(c_ptr), intent(in) :: tm
        integer, intent(in) :: year, month, day, hour, minute, second
        integer(kind=c_int), pointer :: tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year

        call c_f_pointer(tm, tm_sec)
        call c_f_pointer(tm + c_sizeof(tm_sec), tm_min)
        call c_f_pointer(tm + 2*c_sizeof(tm_sec), tm_hour)
        call c_f_pointer(tm + 3*c_sizeof(tm_sec), tm_mday)
        call c_f_pointer(tm + 4*c_sizeof(tm_sec), tm_mon)
        call c_f_pointer(tm + 5*c_sizeof(tm_sec), tm_year)

        tm_sec = second
        tm_min = minute
        tm_hour = hour
        tm_mday = day
        tm_mon = month - 1
        tm_year = year - 1900
    end subroutine tm_set

    subroutine tm_get(tm, year, month, day, hour, minute, second)
        use, intrinsic :: iso_c_binding
        implicit none
        type(c_ptr), intent(in) :: tm
        integer, intent(out) :: year, month, day, hour, minute, second
        integer(kind=c_int), pointer :: tm_sec, tm_min, tm_hour, tm_mday, tm_mon, tm_year

        call c_f_pointer(tm, tm_sec)
        call c_f_pointer(tm + c_sizeof(tm_sec), tm_min)
        call c_f_pointer(tm + 2*c_sizeof(tm_sec), tm_hour)
        call c_f_pointer(tm + 3*c_sizeof(tm_sec), tm_mday)
        call c_f_pointer(tm + 4*c_sizeof(tm_sec), tm_mon)
        call c_f_pointer(tm + 5*c_sizeof(tm_sec), tm_year)

        second = tm_sec
        minute = tm_min
        hour = tm_hour
        day = tm_mday
        month = tm_mon + 1
        year = tm_year + 1900
    end subroutine tm_get

end program time_example

This Fortran program demonstrates various time-related operations:

  1. We start by getting the current time using system_clock.

  2. We then create a specific time using the tm_set subroutine, which is similar to the time.Date function in the original example.

  3. We can extract various components of the time value using the tm_get subroutine.

  4. The program demonstrates how to compare times using the <, >, and == operators.

  5. We calculate the time difference between two times and print it in seconds.

  6. Finally, we show how to add a duration to a time.

To run the program, save it as time_example.f90 and compile it using a Fortran compiler:

$ gfortran time_example.f90 -o time_example
$ ./time_example

This will output the current time, the specified time, various time components, comparisons, and time calculations.

Note that Fortran doesn’t have built-in types for handling times and durations as comprehensively as some other languages. This example uses system_clock and custom subroutines to mimic some of the functionality. For more advanced time handling, you might want to consider using external libraries or more sophisticated time handling modules.