Time in Co-array Fortran

program time_example
  use iso_fortran_env, only: int64
  implicit none

  integer(int64) :: now, then, diff
  character(len=30) :: date_string
  integer :: year, month, day, hour, minute, second

  ! We'll start by getting the current time.
  call date_and_time(values=now)
  call system_clock(now)
  write(*, *) "Current time:", now

  ! You can build a time by providing the year, month, day, etc.
  then = date_to_milliseconds(2009, 11, 17, 20, 34, 58)
  write(*, *) "Then time:", then

  ! You can extract the various components of the time value as expected.
  call milliseconds_to_date(then, year, month, day, hour, minute, second)
  write(*, *) "Year:", year
  write(*, *) "Month:", month
  write(*, *) "Day:", day
  write(*, *) "Hour:", hour
  write(*, *) "Minute:", minute
  write(*, *) "Second:", second

  ! These operations compare two times, testing if the first occurs before, after,
  ! or at the same time as the second, respectively.
  write(*, *) "Then before Now:", then < now
  write(*, *) "Then after Now:", then > now
  write(*, *) "Then equal to Now:", then == now

  ! We can compute the difference between two times.
  diff = now - then
  write(*, *) "Time difference (milliseconds):", diff

  ! We can compute the length of the duration in various units.
  write(*, *) "Hours:", real(diff) / (1000 * 60 * 60)
  write(*, *) "Minutes:", real(diff) / (1000 * 60)
  write(*, *) "Seconds:", real(diff) / 1000

  ! You can use addition to advance a time by a given duration,
  ! or subtraction to move backwards by a duration.
  write(*, *) "Then + diff:", then + diff
  write(*, *) "Then - diff:", then - diff

contains

  function date_to_milliseconds(year, month, day, hour, minute, second) result(milliseconds)
    integer, intent(in) :: year, month, day, hour, minute, second
    integer(int64) :: milliseconds
    
    ! This is a simplified conversion and doesn't account for leap seconds, time zones, etc.
    milliseconds = ((year - 1970) * 365_int64 + (month - 1) * 30_int64 + (day - 1)) * 24 * 60 * 60 * 1000
    milliseconds = milliseconds + hour * 60 * 60 * 1000 + minute * 60 * 1000 + second * 1000
  end function

  subroutine milliseconds_to_date(milliseconds, year, month, day, hour, minute, second)
    integer(int64), intent(in) :: milliseconds
    integer, intent(out) :: year, month, day, hour, minute, second
    integer(int64) :: days, remaining

    days = milliseconds / (24 * 60 * 60 * 1000)
    year = 1970 + int(days / 365)
    month = int((days % 365) / 30) + 1
    day = int((days % 365) % 30) + 1

    remaining = milliseconds % (24 * 60 * 60 * 1000)
    hour = int(remaining / (60 * 60 * 1000))
    minute = int((remaining % (60 * 60 * 1000)) / (60 * 1000))
    second = int((remaining % (60 * 1000)) / 1000)
  end subroutine

end program time_example

This Co-array Fortran program demonstrates time operations similar to the original example. Here’s a breakdown of the changes and adaptations:

  1. We use the iso_fortran_env module to get access to int64 for large integer calculations.

  2. Instead of a time package, we use Fortran’s intrinsic date_and_time and system_clock subroutines to get the current time.

  3. We create custom functions date_to_milliseconds and milliseconds_to_date to convert between date components and milliseconds since the epoch (1970-01-01). This is a simplified version and doesn’t account for all complexities like leap seconds or time zones.

  4. Time comparisons are done using standard Fortran comparison operators (<, >, ==).

  5. Time differences are calculated in milliseconds, and then converted to other units as needed.

  6. Time addition and subtraction are performed directly on the millisecond values.

Note that this is a simplified version of time handling. For more accurate and comprehensive time operations in Fortran, you might want to use external libraries or more sophisticated algorithms to handle time zones, leap seconds, and other complexities.

To run this program, save it to a file (e.g., time_example.f90), compile it with a Fortran compiler that supports Co-array Fortran, and then run the resulting executable.

$ gfortran -fcoarray=single time_example.f90 -o time_example
$ ./time_example

The output will show the current time, the specified “then” time, various time components, comparisons, and time arithmetic results.