Giter VIP home page Giter VIP logo

datetime-fortran's Introduction

datetime-fortran

Actions Status GitHub issues

Date and time manipulation for modern Fortran. The fundamental time step is one millisecond.

Getting started

First, get the code by cloning this repo:

git clone https://github.com/wavebitscientific/datetime-fortran
cd datetime-fortran

or by downloading a release tarball. The latter is recommended if you want to build datetime-fortran with autotools and make.

You can build datetime-fortran with FPM, autotools, CMake, or by simply including the source file "src/datetime_module.f90" in your project. NOTE: Windows additionally requires "src/strptime.cpp" in your project.

FPM

As of version 1.7.0, datetime-fortran can be built using the Fortran Package Manager. Follow the directions on that page to install FPM if you haven't already.

To build, type:

fpm build

binary artifacts are created in:

  • Library and module files: build/gfortran_debug/library
  • test executables: build/gfortran_debug/tests.

To run the tests, type:

fpm test

Autotools

./configure
make check
make install

If you cloned the repo instead of downloading a release tarball, run autoreconf -i first to generate the configure script.

CMake

cmake -B build
cmake --build build

binary artifacts are created in:

  • Library: build/lib/libdatetime
  • module: build/include/datetime.mod
  • test executable: build/bin/datetime_tests

optionally, to install (replace "~/mylibs" with your desired install directory):

cmake -B build -DCMAKE_INSTALL_PREFIX=~/mylibs
cmake --install build

optionally, to run self-tests:

cd build
ctest -V

Use

Start using datetime-fortran in your code by importing derived types from the module:

use datetime_module, only: datetime, timedelta, clock

See some basic examples here.

API

Derived Types

datetime-fortran library provides the following derived types: datetime, timedelta, clock and tm_struct.

datetime

Main date and time object, defined as:

type :: datetime

  !! Main datetime class for date and time representation.

  private

  integer :: year        = 1 !! year [1-HUGE(year)]
  integer :: month       = 1 !! month in year [1-12]
  integer :: day         = 1 !! day in month [1-31]
  integer :: hour        = 0 !! hour in day [0-23]
  integer :: minute      = 0 !! minute in hour [0-59]
  integer :: second      = 0 !! second in minute [0-59]
  integer :: millisecond = 0 !! milliseconds in second [0-999]

  real(kind=real64) :: tz = 0 !! timezone offset from UTC [hours]

  contains

  ! getter functions
  procedure,pass(self),public :: getYear
  procedure,pass(self),public :: getMonth
  procedure,pass(self),public :: getDay
  procedure,pass(self),public :: getHour
  procedure,pass(self),public :: getMinute
  procedure,pass(self),public :: getSecond
  procedure,pass(self),public :: getMillisecond
  procedure,pass(self),public :: getTz

  ! public methods
  procedure,pass(self),public :: isocalendar
  procedure,pass(self),public :: isoformat
  procedure,pass(self),public :: isValid
  procedure,nopass,    public :: now
  procedure,pass(self),public :: secondsSinceEpoch
  procedure,pass(self),public :: strftime
  procedure,pass(self),public :: tm
  procedure,pass(self),public :: tzOffset
  procedure,pass(self),public :: utc
  procedure,pass(self),public :: weekday
  procedure,pass(self),public :: isoweekday
  procedure,pass(self),public :: weekdayLong
  procedure,pass(self),public :: isoweekdayLong
  procedure,pass(self),public :: weekdayShort
  procedure,pass(self),public :: isoweekdayShort
  procedure,pass(self),public :: yearday

  ! private methods
  procedure,pass(self),private :: addMilliseconds
  procedure,pass(self),private :: addSeconds
  procedure,pass(self),private :: addMinutes
  procedure,pass(self),private :: addHours
  procedure,pass(self),private :: addDays

  ! operator overloading procedures
  procedure,pass(d0),private :: datetime_plus_timedelta
  procedure,pass(d0),private :: timedelta_plus_datetime
  procedure,pass(d0),private :: datetime_minus_datetime
  procedure,pass(d0),private :: datetime_minus_timedelta
  procedure,pass(d0),private :: eq
  procedure,pass(d0),private :: neq
  procedure,pass(d0),private :: gt
  procedure,pass(d0),private :: ge
  procedure,pass(d0),private :: lt
  procedure,pass(d0),private :: le

  generic :: operator(+)  => datetime_plus_timedelta,&
                             timedelta_plus_datetime
  generic :: operator(-)  => datetime_minus_datetime,&
                             datetime_minus_timedelta
  generic :: operator(==) => eq
  generic :: operator(/=) => neq
  generic :: operator(>)  => gt
  generic :: operator(>=) => ge
  generic :: operator(<)  => lt
  generic :: operator(<=) => le

endtype datetime

datetime components are initialized by default, so all arguments are optional. Arguments may be provided as positional arguments, in the order of their declaration, or as keyword arguments, in any order. If both positional and keyword arguments are used, no positional arguments may appear after a keyword argument.

Example usage

use datetime_module, only:datetime

type(datetime) :: a

! Initialize as default:
a = datetime() ! 0001-01-01 00:00:00

! Components can be specified by position:
a = datetime(1984, 12, 10) ! 1984-12-10 00:00:00

! Or by keyword:
a = datetime(month=1, day=1, year=1970) ! 1970-01-01 00:00:00

! Or combined:
a = datetime(2013, 2, minute=23, day=5) ! 2013-02-05 00:23:00

! With timezone offset:
a = datetime(2013, 2, minute=23, day=5, tz=-4) ! 2013-02-05 00:23:00 -0400

! Do not use positional after keyword arguments:
a = datetime(year=2013, 2, minute=23, day=5) ! ILLEGAL

Note that the current implementation of datetime does not support daylight saving time (DST) information.

See also

Back to top


getYear

pure elemental integer function getYear(self)
  class(datetime),intent(in) :: self

Returns the year of a datetime instance.

Back to top


getMonth

pure elemental integer function getMonth(self)
  class(datetime),intent(in) :: self

Returns the month of a datetime instance.

Back to top


getDay

pure elemental integer function getDay(self)
  class(datetime),intent(in) :: self

Returns the day of a datetime instance.

Back to top


getHour

pure elemental integer function getHour(self)
  class(datetime),intent(in) :: self

Returns the hour of a datetime instance.

Back to top


getMinute

pure elemental integer function getMinute(self)
  class(datetime),intent(in) :: self

Returns the minute of a datetime instance.

Back to top


getSecond

pure elemental integer function getSecond(self)
  class(datetime),intent(in) :: self

Returns the second of a datetime instance.

Back to top


getMillisecond

pure elemental integer function getMillisecond(self)
  class(datetime),intent(in) :: self

Returns the millisecond of a datetime instance.

Back to top


isocalendar

function isocalendar(self)
  class(datetime),intent(in) :: self
  integer,dimension(3)       :: isocalendar

Returns an array of 3 integers: year, week number, and week day, as defined by ISO 8601 week date. The ISO calendar is a widely used variant of the Gregorian calendar. The ISO year consists of 52 or 53 full weeks. A week starts on a Monday (1) and ends on a Sunday (7). The first week of an ISO year is the first (Gregorian) calendar week of a year containing a Thursday. This is called week number 1, and the ISO year of that Thursday is the same as its Gregorian year.

datetime%isocalendar() is equivalent to Python's datetime.datetime.isocalendar().

Example usage

use datetime_module,only:datetime

type(datetime) :: a

a = datetime(2013,1,1)
print *, a % isocalendar() ! Prints: 2013  1  2

See also

Back to top


isoformat

pure elemental character(len=23) function isoformat(self,sep)
  class(datetime), intent(in)          :: self
  character(len=1),intent(in),optional :: sep

Returns a character string of length 23 that contains date and time in ISO 8601 format.

datetime%isoformat() is equivalent to Python's datetime.datetime.isoformat(), with the only difference being that datetime%isoformat() returns the milliseconds at the end of the string, where as datetime.datetime.isoformat() returns microseconds.

Arguments

sep is an optional argument that specifies which character of length 1 will separate date and time entries. If ommited, defaults to T.

Example usage

use datetime_module,only:datetime

type(datetime) :: a

a = datetime(1984,12,10,13,5,0)

! Without arguments:
print *, a % isoformat() ! Prints 1984-12-10T13:05:00.000

! With a specified separator:
print *, a % isoformat(' ') ! Prints 1984-12-10 13:05:00.000

See also

Back to top


isValid

pure elemental logical function isValid(self)
  class(datetime),intent(in) :: self

Returns .true. if all datetime instance components have valid values, and .false. otherwise. Components have valid values if they are within the range indicated in datetime derived type description.

Useful for debugging and validating user input.

Example usage

use datetime_module,only:datetime

type(datetime) :: a

a = datetime(1984,12,10,13,5,0)

print *, a % isValid()! .true.

a = datetime(1984,13,10,13,5,0)

print *, a % isValid() ! .false.

See also

Back to top


now

type(datetime) function now(self)
  class(datetime),intent(in) :: self

Returns the datetime instance representing the current machine time. Does not support timezones.

Return value

self A datetime instance with current machine time.

Example usage

use datetime_module,only:datetime

type(datetime) :: a

a = a % now() ! Assigns current machine time to a

Back to top


secondsSinceEpoch

integer function secondsSinceEpoch(self)
  class(datetime),intent(in) :: self

Returns an integer number of seconds since the UNIX Epoch, 1970-01-01 00:00:00 +0000 (UTC).

Return value

secondsSinceEpoch An integer scalar containing number of seconds since UNIX Epoch.

Example usage

use datetime_module,only:datetime

type(datetime) :: a

! Initialize:
a = datetime(2013,1,1)

print *, a%secondsSinceEpoch()

Back to top


strftime

character(len=maxstrlen) function strftime(self,format)
  class(datetime), intent(in) :: self
  character(len=*),intent(in) :: format

A datetime-bound method that serves as a wrapper around the C routine strftime. datetime%strftime takes only the format string as argument, and returns the character string representation of the time information contained in the datetime instance. Thus, this function takes care of the conversion to tm_struct and calling the raw C strftime. Because Fortran does not allow assumed-length character strings as the type of the function result, a fixed length of MAXSTRLEN is used. MAXSTRLEN is currently set to 99. It is assumed that the desired time string is shorter than this value. Any resulting string shorter than MAXSTRLEN is padded with spaces, so it is best to trim the result using the TRIM intrinsic function (see the usage example below). This datetime-bound method is available since version 0.3.0.

Arguments

format A character string describing the desired format of date and time. Same as the format for the raw C strftime.

Return value

A character(len=maxstrlen) representation of datetime using format.

Example usage

use datetime_module

type(datetime)  :: a

a = a % now()
print *, a % isoformat()

print *, trim(a % strftime("%Y %B %d"))

See also

Back to top


tm

pure elemental type(tm_struct) function tm(self)
  CLASS(datetime),intent(in) :: self

Returns a tm_struct instance that matches the time and date information in the caller datetime instance.

Example usage

use datetime_module,only:datetime

type(datetime)  :: a
type(tm_struct) :: tm

! Initialize:
a = datetime(2013,1,1)

! Get tm_struct from datetime:
tm = a % tm()

See also

Back to top


tzOffset

pure elemental character(len=5) function tzOffset(self)
  class(datetime),intent(in) :: self

Given a datetime instance, returns a character string with timezone offset in hours from UTC (Coordinated Universal Time), in format +hhmm or -hhmm, depending on the sign, where hh are hours and mm are minutes.

Arguments

None.

Return value

tzOffset A character(len=5) in the form +hhmm or -hhmm, depending on the sign.

Example usage

use datetime_module,only:datetime

type(datetime)  :: a
type(tm_struct) :: tm

! Initialize a datetime instance with timezone offset of -4.75 hours:
a = datetime(2013,1,1,tz=-4.75)

! Write tzOffset on screen:
print *, a % tzOffset ! -0445 (offset of 4 hours and 45 minutes)

Back to top


utc

pure elemental type(datetime) function utc(self)
  class(datetime),intent(in) :: self

Returns the datetime instance at Coordinated Universal Time (UTC).

Return value

utc A datetime instance with at UTC (tz = 0).

Example usage

use datetime_module,only:datetime

type(datetime)  :: a
type(tm_struct) :: tm

! Initialize a datetime instance with timezone offset of -4.75 hours:
a = datetime(2013,1,1,tz=-4.75)

print *, a % isoformat() // a % tzOffset() ! 2013-01-01T00:00:00.000-0445

! Convert a to UTC:
a = a % utc()

print *, a % isoformat() // a % tzOffset() ! 2013-01-01T04:45:00.000+0000

See also

Back to top


weekday

pure elemental integer function weekday(self)
  class(datetime),intent(in) :: self

A datetime-bound method to calculate day of the week using Zeller's congruence. Returns an integer scalar in the range of [0-6], starting from Sunday.

Example usage

use datetime_module,only:datetime

type(datetime)  :: a

! Initialize:
a = datetime(2013,1,1)

print *, a % weekday() ! 2

See also

Back to top


weekdayLong

pure elemental character(len=9) function weekdayLong(self)
  class(datetime),intent(in) :: self

Returns the full name of the day of the week.

Example usage

use datetime_module,only:datetime

type(datetime)  :: a

! Initialize:
a = datetime(2013,1,1)

print *, a % weekdayLong() ! Tuesday

See also

Back to top


weekdayShort

pure elemental character(len=3) function weekdayShort(self)
  class(datetime),intent(in) :: self

Returns the abbreviated (e.g. Mon) name of the day of the week.

Example usage

use datetime_module,only:datetime

type(datetime)  :: a

! Initialize:
a = datetime(2013,1,1)

print *, a % weekdayShort() ! Tue

See also

Back to top


yearday

pure elemental integer function yearday(self)
  class(datetime),intent(in) :: self

datetime-bound procedure. Returns integer day of the year (ordinal date). Equals to 1 for any January 1, 365 for a December 31 on a non-leap year, and 366 for a December 31 on a leap year.

Example usage

use datetime_module,only:datetime

type(datetime)  :: a

! Initialize:
a = datetime(2013,5,1)

print *, a % yearday() ! 121

See also

Back to top


timedelta

Represents a duration of time, and a difference between two datetime objects. It is defined as:

type :: timedelta

  !! Class of objects that define difference between two datetime
  !! instances.

  private

  integer :: days         = 0 !! number of days
  integer :: hours        = 0 !! number of hours
  integer :: minutes      = 0 !! number of minutes
  integer :: seconds      = 0 !! number of seconds
  integer :: milliseconds = 0 !! number of milliseconds

  contains

  ! getter functions
  procedure,pass(self),public :: getDays
  procedure,pass(self),public :: getHours
  procedure,pass(self),public :: getMinutes
  procedure,pass(self),public :: getSeconds
  procedure,pass(self),public :: getMilliseconds

  ! public methods
  procedure,public :: total_seconds

  ! operator overloading procedures
  procedure,private :: timedelta_plus_timedelta
  procedure,private :: timedelta_minus_timedelta
  procedure,private :: unary_minus_timedelta
  procedure,private :: eq
  procedure,private :: neq
  procedure,private :: gt
  procedure,private :: ge
  procedure,private :: lt
  procedure,private :: le

  generic :: operator(+)  => timedelta_plus_timedelta
  generic :: operator(-)  => timedelta_minus_timedelta,&
                             unary_minus_timedelta
  generic :: operator(==) => eq
  generic :: operator(/=) => neq
  generic :: operator(>)  => gt
  generic :: operator(>=) => ge
  generic :: operator(<)  => lt
  generic :: operator(<=) => le

endtype timedelta

All arguments are optional and default to 0. Similarly to datetime objects, timedelta instances can be initialized using positional and/or keyword arguments. In addition, a timedelta object is a result of subtraction between two datetime objects.

Example usage

use datetime_module

type(datetime)  :: a,b
type(timedelta) :: c

! Initialize as default
c = timedelta()

! Positional arguments:
c = timedelta(0,1,15,0,0) ! 1 hour and 15 minutes

! Keyword arguments:
c = timedelta(days=1,hours=12) ! 1 day and 12 hours

! Difference between datetimes:
a = datetime(2013,5,12,22,0,0) ! 2013-05-12 22:00:00
b = datetime(2012,9,18,14,0,0) ! 2012-09-18 14:00:00

! Subtract to get timedelta:
c = a-b

Back to top


total_seconds

pure elemental real(kind=real_dp) function total_seconds(self)
  class(timedelta), intent(in) :: self

A timedelta-bound method that returns a number of seconds contained in the time interval defined by the timedelta instance. This method is equivalent to Python's datetime.timedelta.total_seconds function.

Return value

total_seconds A total number of seconds (of type real(kind=real_dp)) contained in the timedelta instance.

Example usage

use datetime_module,only:timedelta

type(timedelta) :: td

td = timedelta(days=5,hours=12,minutes=15,seconds=7,milliseconds=123)

print *, td%total_seconds() ! 476107.12300000002

Back to top


clock

A generic clock object that contains start and stop times, tick increment and reset and tick methods. Most useful when needing to keep track of many datetime instances that change at different rates, for example, physical models with different time steps.

Definition:

type :: clock

  !! A clock object with a start, stop and current times, tick interval
  !! and tick methods.

  type(datetime) :: startTime
  type(datetime) :: stopTime
  type(datetime) :: currentTime

  type(timedelta) :: tickInterval

  logical :: alarm = .false.

  ! Clock status flags
  logical :: started = .false.
  logical :: stopped = .false.

  contains

  procedure :: reset
  procedure :: tick

endtype clock

clock instance must be initialized with some sane values of clock%startTime, clock%stopTime and clock%tickIncrement in order to be useful.

Example usage

use datetime_module

type(clock)    :: myClock
type(datetime) :: myTime

! Initialize myTime
myTime = myTime%now()

! Initialize myClock
! Starts from myTime, stops 1 hour later, 1 minute per tick
myClock = clock(startTime    = myTime,                   &
                stopTime     = myTime+timedelta(hours=1),&
                tickInterval = timedelta(minutes=1))

do

  call myClock % tick()

  ! Report current time after each tick
  print *, myClock % currentTime % isoformat(' ')

  ! If clock has reached stopTime, exit loop
  if(myClock % stopped)THEN
    exit
  endif

enddo

See also

Back to top


reset

pure elemental subroutine reset(self)
  class(clock),intent(inout) :: self

Resets the clock to its start time.

Example usage

call myClock%reset() ! Resets myClock%currentTime to myClock%startTime

Back to top


tick

pure elemental subroutine tick(self)
  class(clock),intent(inout) :: self

Increments the currentTime of the clock instance by one tickInterval. Sets the clock%stopped flag to .TRUE. if clock%currentTime equals or exceeds clock%stopTime.

Example usage

See clock for an example.

See also

Back to top


tm_struct

Time object compatible with C/C++ tm struct. Available mainly for the purpose of calling c_strftime and c_strptime procedures.

type,bind(c) :: tm_struct

  !! A derived type provided for compatibility with C/C++ time struct.
  !! Allows for calling strftime and strptime procedures through the
  !! iso_c_binding.

  integer(kind=c_int) :: tm_sec   !! Seconds      [0-60] (1 leap second)
  integer(kind=c_int) :: tm_min   !! Minutes      [0-59]
  integer(kind=c_int) :: tm_hour  !! Hours        [0-23]
  integer(kind=c_int) :: tm_mday  !! Day          [1-31]
  integer(kind=c_int) :: tm_mon   !! Month        [0-11]
  integer(kind=c_int) :: tm_year  !! Year - 1900
  integer(kind=c_int) :: tm_wday  !! Day of week  [0-6]
  integer(kind=c_int) :: tm_yday  !! Days in year [0-365]
  integer(kind=c_int) :: tm_isdst !! DST          [-1/0/1]

endtype tm_struct

See also

Back to top


Overloaded operators

datetime-fortran provides arithmetic and comparison operators for datetime and timedelta objects.

Arithmetic operators

Addition (+) and subtraction (-) operators are available for the following combination of derived type pairs:

  • datetime + timedelta, returns a datetime instance;

  • timedelta + datetime, returns a datetime instance;

  • timedelta + timedelta, returns a timedelta instance;

  • timedelta - timedelta, returns a timedelta instance;

  • datetime - datetime, returns a timedelta instance;

  • -timedelta (unary minus), returns a timedelta instance.

Note that datetime - datetime operation accounts for timezone (tz) offsets in each of the datetime instances. The resulting timedeltathus includes the difference between timezones.

Comparison operators

datetime-fortran supports following binary comparison operators for datetime and timedelta objects: ==, /=, >, >=, < and <=.

Since version 1.0.5, all comparison operators respect the timezone parameter of the datetime instances, so the operands are first adjusted to UTC time before making the comparison.

Back to top


Public procedures

c_strftime

function c_strftime(str,slen,format,tm) bind(c,name='strftime') result(rc)
  character(kind=c_char),dimension(*),intent(out) :: str
  integer(kind=c_int),value,          intent(in)  :: slen
  character(kind=c_char),dimension(*),intent(in)  :: format
  type(tm_struct),                    intent(in)  :: tm
  integer(kind=c_int)                             :: rc

An interface to a C/C++ standard library routine. Copies into str the content of format, expanding its format specifiers into the corresponding values that represent the time described in tm, with a limit of slen characters.

Note: This function was renamed from strftime to c_strftime in version 0.3.0 to avoid name conflict with datetime-bound method strftime. If working with datetime instances, use datetime%strftime instead.

Arguments

str is the destination character string with the requested date and time.

slen is the maximum number of characters to be copied to str, including the terminating null-character, char(0).

format is the character string containing any combination of regular characters and special format specifiers. These format specifiers are replaced by the function to the corresponding values to represent the time specified in tm. For more information on format specifiers see http://www.cplusplus.com/reference/ctime/strftime/.

tm is an instance of the type tm_struct, containing date and time values to be processed.

Return value

If the resulting string fits in less than slen characters including the terminating null-character, the total number of characters copied to str (not including the terminating null-character) is returned. Otherwise, zero is returned and the contents of the array are indeterminate.

Example usage

use datetime_module

type(datetime)    :: a
character(len=20) :: res
integer           :: rc

a = a % now()

rc = c_strftime(res,20,"%Y %B %d"//CHAR(0),a%tm())

See also

Back to top


c_strptime

function c_strptime(str,format,tm) bind(c,name='strptime') result(rc)
  character(kind=c_char),dimension(*),intent(in)  :: str
  character(kind=c_char),dimension(*),intent(in)  :: format
  type(tm_struct),                    intent(out) :: tm
  character(kind=c_char,len=1)                    :: rc

An interface to a C/C++ standard library routine. Converts the character string str to values which are stored in tm, using the format specified by format.

Note: This function was renamed from strptime to c_strptime in version 0.3.0 to avoid name conflicts with strptime which operates on datetime instances. If working with datetime instances, use strptime instead.

Arguments

str is the character string containing date and time information.

format is the character string containing any combination of regular characters and special format specifiers, describing the date and time information in str.

tm is an instance of the type tm_struct, in which the date and time values will be filled upon successful completion of the c_strptime function.

Return value

Upon successful completion, c_strptime returns the character following the last character parsed. Otherwise, a null character is returned.

Example usage

Extracting time difference between two time strings using c_strptime and tm2date:

use datetime_module

type(datetime)  :: date1,date2
type(tm_struct) :: ctime
type(timedelta) :: timediff

! Return code for strptime
character(len=1) :: rc

! Example times in "YYYYMMDD hhmmss" format
character(len=15) :: str1 = "20130512 091519"
character(len=15) :: str2 = "20131116 120418"

! Get tm_struct instance from str1
rc = c_strptime(str1,"%Y%m%d %H%M%S"//char(0),ctime)
date1 = tm2date(ctime)

! Get tm_struct instance from str2
rc = c_strptime(str2,"%Y%m%d %H%M%S"//char(0),ctime)
date2 = tm2date(ctime)

timediff = date2-date1

print *, timediff
print *, timediff % total_seconds()

This example outputs the following:

        188           2          48          58        1000
   16253339.0000000

See also

Back to top


date2num

pure elemental real(kind=real_dp) function date2num(d)
  type(datetime),intent(in) :: d

Returns the number of days since 0001-01-01 00:00:00 UTC, given a datetime instance d.

This function is similar in what it returns to analogous functions in Python (matplotlib.dates.date2num) and MATLAB's datenum. Note that matplotlib.dates.date2num returns the number of days since 0001-01-01 00:00:00 UTC plus 1 (for historical reasons), and MATLAB's datenum returns the number of days since 0000-01-01 00:00:00 UTC. In datetime-fortran, we choose the reference time of 0001-01-01 00:00:00 UTC as we consider it to be the least astonishing for the average user. Thus, MATLAB and Python users should be cautious when using datetime-fortran's date2num() function.

Since version 1.0.5, date2num is timezone aware, i.e. the datetime instance is first converted to UTC before calculating the number of days.

date2num is the inverse function of num2date, so by definition, a % utc() == num2date(date2num(a)) evaluates as .true. for any datetime instance a.

Arguments

d A datetime instance.

Return value

date2num A REAL(KIND=real64) number of days since 0001-01-01 00:00:00 UTC.

Example usage

use datetime_module,only:datetime,date2num

type(datetime)  :: a

! Initialize:
a = datetime(2013,1,1,6)

print *, date2num(a) ! 734869.25000000000

See also

Back to top


datetimeRange

pure function datetimeRange(d0,d1,t)
  type(datetime), intent(in) :: d0
  type(datetime), intent(in) :: d1
  type(timedelta),intent(in) :: t

Given start and end datetime instances d0 and d1, and time increment as timedelta instance t, returns an array of datetime instances. The number of elements is the number of whole time increments contained between datetimes d0 and d1.

Arguments

d0 A datetime instance with start time. Will be the first element of the resulting array.

d1 A datetime instance with end time. Will be the equal to or greater than the last element of the resulting array.

t A timedelta instance being the time increment for the resulting array.

Return value

datetimeRange An array of datetime instances of length floor((d1-d0)/t)+1

Example usage

type(datetime)  :: a,b
type(timedelta) :: td

type(datetime),dimension(:),allocatable :: dtRange

a  = datetime(2014,5,1)
b  = datetime(2014,5,3)
td = timedelta(days=1)

dtRange = datetimeRange(a,b,td)

! Returns:
!
! dtRange = [datetime(2014,5,1),
!            datetime(2014,5,2),
!            datetime(2014,5,3)]

a  = datetime(2014,5,1)
b  = datetime(2014,5,3)
td = timedelta(hours=7)

dtRange = datetimeRange(a,b,td)

! Returns:
!
! dtRange = [datetime(2014,5,1,0),
!            datetime(2014,5,1,7),
!            datetime(2014,5,1,14),
!            datetime(2014,5,1,21),
!            datetime(2014,5,2, 4),
!            datetime(2014,5,2,11),
!            datetime(2014,5,2,18)]

See also

Back to top


daysInMonth

pure elemental integer function daysInMonth(month,year)
  integer,intent(in) :: month
  integer,intent(in) :: year

Returns the number of days in month for a given month and year. This function is declared as elemental, so it can be called with scalar or n-dimensional array arguments.

Arguments

month Integer number of month in year. Valid values are in the range [1-12].

year Integer year.

Return value

Returns an integer number of days in requested month and year. Returns 0 if month is not in valid range.

Example usage

use datetime_module,only:daysInMonth

! January on leap year:
print *, daysInMonth(1,2012)   ! 31

! February on leap year:
print *, daysInMonth(2,2012)   ! 29

! February on non-leap year
print *, daysInMonth(2,2013)   ! 28

See also

Back to top


daysInYear

pure elemental integer Function daysInYear(year)
  integer,intent(in) :: year

Given an integer year, returns an integer number of days in that year. Calls the isLeapYear function.

Arguments

year An integer scalar or array containing the desired year number(s).

Return value

daysInYear An integer scalar or array. Represents the number of days in year.

Example usage

use datetime_module,only:daysInYear

! Leap year:
print *, daysInYear(2012) ! 366

! Non-leap year:
print *, daysInYear(2013) ! 365

See also

Back to top


isLeapYear

pure elemental logical function isLeapYear(year)
  integer,intent(in) :: year

Returns a logical value indicating whether the reqested year is a leap year.

Arguments

year An integer scalar or array representing year number.

Return value

isLeapYear A logical scalar or array indicating whether a given year is leap year.

Example usage

use datetime_module,only:isLeapYear

! Leap year:
print *, isLeapYear(2012) ! .true.

! Non-leap year:
print *, isLeapYear(2013) ! .false.

See also

Back to top


num2date

pure elemental type(datetime) function num2date(num)
  real(kind=real_dp),intent(in) :: num

Given the number of days since 0001-01-01 00:00:00 UTC, returns a correspoding datetime instance.

This function is similar to analogous function in Python (matplotlib.dates.num2date).

num2date is the inverse function of date2num, so by definition, a == num2date(date2num(a)) evaluates as .true. for any datetime instance a. Similarly, b == date2num(num2date(b)) evaluates as .true. for any variable b of type real(kind=real64).

Arguments

num Number of days since 0001-01-01 00:00:00 UTC.

Return value

num2date A datetime instance.

Example usage

use datetime_module,only:datetime,num2date

type(datetime)  :: a

a = num2date(734869.25d0) ! a becomes datetime(2013,1,1,6,0,0,0)

See also

Back to top


strptime

type(datetime) function strptime(str,format)
  character(len=*),intent(in) :: str
  character(len=*),intent(in) :: format

A wrapper function around c_strptime. Given a character string str with the format format, returns an appropriate datetime instance containing that time information. This function is analogous to Python's datetime.datetime.strptime() function. Available since version 0.3.0.

Arguments

str is the character string containing date and time information.

format is the character string containing any combination of regular characters and special format specifiers, describing the date and time information in str.

Return value

Upon successful completion, strptime returns the datetime instance corresponding to the time information contained in str.

Example usage

Extracting time difference between two time strings using strptime:

use datetime_module

type(datetime)  :: date1,date2
type(timedelta) :: timediff

! Example times in "YYYYMMDD hhmmss" format
character(len=15) :: str1 = "20130512 091519"
character(len=15) :: str2 = "20131116 120418"

date1 = strptime(str1,"%Y%m%d %H%M%S")
date2 = strptime(str2,"%Y%m%d %H%M%S")

timediff = date2-date1

print *, timediff
print *, timediff%total_seconds()

This example outputs the following:

        188           2          48          58        1000
   16253339.0000000

This is the same example as in c_strptime but with fewer necessary steps.

See also

Back to top


tm2date

pure elemental type(datetime) function tm2date(ctime)
  type(tm_struct),intent(in) :: ctime

Given a tm_struct instance, returns a corresponding datetime instance. Mostly useful for obtaining a datetime instance after a tm_struct is returned from strptime.

Arguments

ctime A tm_struct instance.

Return value

tm2date A datetime instance.

Example usage

See example usage for strptime.

See also

machinetimezone

real(real64) function machinetimezone()

returns the machine's time zone in hours.

Arguments

None

Return value

real(real64) A tz value.

Example usage

Extracting your local machine's time zone information.

type(datetime) :: date
date = datetime(1970, 1, 1, tz=machinetimezone())

See also

Back to top


epochdatetime

pure elemental type(datetime) function epochdatetime()
    epochdatetime = datetime(1970,1,1,0,0,0,0,tz=0.)

returns a datetime that corresponds to the UNIX epoch.

Arguments

None

Return value

type(datetime) A datetime(1970,1,1,0,0,0,0,tz=0.0) value.

Example usage

type(datetime) :: epochday
epochday = epochdatetime()

See also

Back to top


localtime

  pure elemental type(datetime) function localtime(epoch, tz)
    ! Returns a `datetime` instance from epoch.
    ! tz can be obtained from `machinetimezone`
    integer(int64),intent(in) :: epoch
    real(real64),intent(in) :: tz !! local machine time zone information

Generating a datetime type from epoch and timezone.

Arguments

epoch A epoch time (second)

tz A time zone (hour). This value can be generated by using machinetimezone

Return value

type(datetime) A datetime instance.

Example usage

Convert the epoch seconds to an expression in your machine's time zone.

integer(int64), parameter :: epoch = 3600
real(real64) :: tz
type(datetime) :: date
tz = machinetimezone()
date = localtime(epoch, tz)

See also

Back to top


gmtime

  pure elemental type(datetime) function gmtime(epoch)
    ! Returns a `datetime` instance from epoch.
    integer(int64),intent(in) :: epoch

Generating a datetime type from epoch.

Arguments

epoch A epoch time (second)

Return value

type(datetime) A datetime instance. Result is represented with UTC time.

Example usage

Convert the epoch seconds to an expression in UTC time zone.

integer(int64) :: epoch = 3600
type(datetime) :: day
day = gmtime(epoch)

See also

Back to top


datetime-fortran's People

Contributors

guziy avatar milancurcic avatar penguian avatar sakamoti avatar scivision avatar szaghi avatar tcanich avatar zbeekman avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

datetime-fortran's Issues

Problem adding time delta(minutes=60*n)

Consider this example:

    !Test t - dt
    d = datetime(1980, 1, 1, 0, 0)
    print *, 't = ', d
    print *, 't - 6h = ', d + timedelta(hours=-6)
    print *, 't - 360min = ', d + timedelta(minutes=-360)

Output:

t =         1980           1           1           0           0           0           0   0.00000000    
 t - 6h =         1979          12          31          18           0           0           0   0.00000000    
 t - 360min =         1979          12          31          17          60           0           0   0.00000000    

I've done a test to catch this and a fix... Though I had to rename the module file to have the same name as the module, otherwise my eclipse project could not find it... I'll try to break it into 2 pull requests, test and fix.

Cheers

configure is insensitive to FCFLAGS

Specifying FCFLAGS when running configure, for example:

$ FCFLAGS=-O3 FC=ifort ./configure

does not affect what flags are being used when running make. In fact, the flags are always -Wall -O0 -C -fbacktrace, which are the gfortran flags hardwired in src/lib/Makefile.am:

# Items needed specifically by autotools
AM_FCFLAGS = -Wall -O0 -C -fbacktrace

Specifying FC works as expected.

@blippy can you look into this at your convenience? Thanks!

Clean up README.md

README.md is overdue for a clean-up, like removing API docs for now-private methods etc.

timing codes

@milancurcic

Hi Milan,

I searched into doc and past issues, but I was not able to find an answer.

Is it possible to use datetime as a tic toc instrumenting-library to profile Fortran codes?

I mean, is it possible to use datetime class to (accurately) measure the time taken from blocks of code?

I am almost sure to have already asked this, but my memory is going to have many IO errors these days...

Cheers.

Generic procedure including a sub-class of TimeDelta

I faced a problem with a sub-class of timedelta.
I defined a generic procedure name for operator(+) (as below, can be compiled),
but the program executes the operator for TimeDelta, not for RelativeDelta.

type, extends(TimeDelta) :: RelativeDelta
***
end type RelativeDelta

interface operator(+)
    module procedure datetime_plus_relativedelta
    module procedure relativedelta_plus_datetime
end interface operator(+)

One possible reason is class in the original datetime_plus_timedelta function.
While type(timedelta) indicates only timedelta class, class(timedelta) does sub-classes in addition to timedelta class.

pure elemental function datetime_plus_timedelta(d0,t) result(d)
  class(datetime), intent(in) :: d0 !! `datetime` instance
  class(timedelta),intent(in) :: t  !! `timedelta` instance

Could you update the attribute from class to type in non-method procedures?
Or what can I do for overloading of such a function?
I will appreciate your help with this issue.

Unit tests

Unit tests for all classes and methods.

User-defined constructor issues with Intel Fortran

Noticed this behavior some time ago but haven't had the chance to look deeper into it. Currently, the datetime-fortran builds and passes tests when built with gfortran (here with 5.2.0 but I think 4.9 and later should work):

FC=gfortran ./configure
make check

However with ifort (15.0.0 here, same behavior with 16.0.0):

FC=ifort ./configure
make check

The library itself builds successfully but building tests fails with a lot of errors. First few are:

ifort -c -g -I../lib datetime_tests.f90
datetime_tests.f90(155): error #6355: This binary operation is invalid for this data type.
  tests(n) = assert(datetime() == datetime(1,1,1),&
--------------------^
datetime_tests.f90(155): error #6355: This binary operation is invalid for this data type.
  tests(n) = assert(datetime() == datetime(1,1,1),&
----------------------------------^

It looks like ifort does not recognize the == operator for datetime types (overloaded by function eq in mod_datetime.f90). Why not? I tried to minimize the error-reproducing test code:

use datetime_module,only:datetime

implicit none

type(datetime) :: a,b

a = datetime()
write(*,*)a % isoformat()

b = datetime(1,1,1)
write(*,*)b % isoformat()

! This compiles and works with both gfortran and ifort:
write(*,*)a == b

! This compiles and works with gfortran; does not compile with ifort:
write(*,*)datetime() == datetime(1,1,1)

end

See, if I first assign datetime instances to variables a and b, then ifort knows how to make the a == b comparison. But somehow, it cannot do it "on the fly", i.e. datetime() == datetime(1,1,1). To test this, I make the minimal example in which I define a simple type, overload it's constructor with a function, and overload the == operator with the function eq:

module test
implicit none

type :: mytype

  private
  integer :: a

  contains

  procedure,private :: eq
  generic :: operator(==) => eq

endtype mytype

interface mytype
  module procedure :: mytype_constructor
endinterface mytype

contains

type(mytype) function mytype_constructor(a)
  integer,intent(in),optional :: a
  if(present(a))then
    mytype_constructor % a = a
  else
    mytype_constructor % a = 0
  endif
endfunction mytype_constructor


logical function eq(m0,m1)
  class(mytype),intent(in) :: m0,m1
  eq = m0 % a == m1 % a
endfunction eq

endmodule test


program testprog
use test
implicit none 

write(*,*)mytype() == mytype(0)

endprogram testprog

However, this minimal example works with ifort, and mytype() == mytype(0) evaluates as expected. So perhaps this is not the issue, but something else is. What am I missing?

Thanks!!

Homebrew packaging

In thread #22 (comment)

@zeekman said: "@blippy I agree, but I am just talking about what is needed for Homebrew to accept the "formula". It needs to have a test do block that will compile code, link it against diatomite-fortran and run it to verify it all went well... I'll dig in the src/tests directory, and find something there."

and: "@milancurcic and @blippy: I've got the Homebrew formula all set, including the test do block etc.
All I'm waiting on now is for @milancurcic to mint a release that includes configure.sh in the tarball.
@blippy also, one more question for you: Will pkg-config always be a build dependency, or just when configure.sh is missing? (Right now I am testing the formula installing the HEAD (i.e. github master) and listing automake and autoconf and pkg-config as build dependencies, but I wonder if I'll need pkg-config as a normal build dep"

Build failure on gfortran 4.8.2

On the page https://github.com/milancurcic/datetime-fortran it states that the project has been tested on gfortran 4.8.2 (which is in Debian stable). Unfortunately, this produces a build failure:

gfortran -c -Wall -O0 -C -fbacktrace mod_datetime.f90
mod_datetime.f90:846.6:

  d = d0
      1
Error: Can't convert CLASS(datetime) to TYPE(datetime) at (1)
make[1]: *** [mod_datetime.o] Error 1

So you need to either fix the docs on the page indicated, or modify the code.

Error invoking datetime constructor with ifort-17.0.5

Have intel/17.0.5.239 Isn't that how it is supposed to work?
Thanks,
Mariusz

PROGRAM test

USE datetime_module, ONLY: datetime, timedelta

IMPLICIT NONE

TYPE(datetime) :: utctime

! utctime=datetime(2013,1,1,tz=-5)
utctime=datetime(year=2013,month=1,year=1)

! PRINT *,utctime%utc

END PROGRAM test

make test.x
ifort -c -L/apps/netcdf/4.3.0-intel/lib -lnetcdff -lnetcdf -I/apps/netcdf/4.3.0-intel/include -L/home/Mariusz.Pagowski/codes/datetime-fortran/build/lib -ldatetime -I/home/Mariusz.Pagowski/codes/datetime-fortran/build/include test.f90
test.f90(10): error #6053: Structure constructor may not have fields with the PRIVATE attribute [YEAR]
utctime=datetime(year=2013,month=1,year=1)
-------------------^
test.f90(10): error #6053: Structure constructor may not have fields with the PRIVATE attribute [MONTH]
utctime=datetime(year=2013,month=1,year=1)
-----------------------------^
test.f90(10): error #8211: This component-spec has already been specified. [YEAR]
utctime=datetime(year=2013,month=1,year=1)
-------------------------------------^
test.f90(10): error #6053: Structure constructor may not have fields with the PRIVATE attribute [YEAR]
utctime=datetime(year=2013,month=1,year=1)
-------------------------------------^
compilation aborted for test.f90 (code 1)
make: *** [test.o] Error 1

"undefined reference" when using datetime-fortran

Hi,

I'm a relatively new fortran user, with little experience using external libraries.
I'm on Ubuntu 16.04 with gfortran 5.4.0
I installed datetime-fortran using the instructions:

git clone https://github.com/wavebitscientific/datetime-fortran
cd datetime-fortran
autoreconf -i
./configure
make check
make install prefix=/home/rfapostolo/code/datetime-fortran

However, when I try to run anything using the module, I get "undefined reference to ...", MWE using the first example:

test_dt.f08

program test_dt
use datetime_module,only:datetime

      type(datetime) :: a

      a = datetime(2013,1,1)
      write(*,*)a % isocalendar() ! Prints: 2013  1  2

end program test_dt

trying to compile with:

f95 -o test_dt  -g -I/home/rfapostolo/code/datetime-fortran/include -L/home/rfapostolo/code/proper/datetime-fortran/lib test_dt.f08

Results in:

/tmp/ccMAIMs7.o: In function `MAIN__':
/home/rfapostolo/Dropbox/code/proper/propc/test_dt.f08:6: undefined reference to `__mod_datetime_MOD_datetime_constructor'
/home/rfapostolo/Dropbox/code/proper/propc/test_dt.f08:7: undefined reference to `__mod_datetime_MOD___vtab_mod_datetime_Datetime'
/home/rfapostolo/Dropbox/code/proper/propc/test_dt.f08:7: undefined reference to `__mod_datetime_MOD_isocalendar'
collect2: error: ld returned 1 exit status

I'd really appreciate if you could point me to my mistake.

Remove Makefile.ori files

The project has a number of files called Makefile.ori. These were the orginal makefiles. Now that autotools has been implemented successfully, they are redundant and can be removed from the project wherever they exist.

Bug in function now()

There is a bug in the file "mod_datetime.f90".
type(datetime) function now()
...
now % tz = hour+minute*m2h
Codes should be change to
now % tz = hour+sign(minute,hour)*m2h
or
now % tz = values(4)*m2h

Bug in `datetime % secondsSinceEpoch`

Calling datetime % secondsSinceEpoch() fails when called with a datetime instance with the value later than approximately datetime(2001,9,9) with the internal formatted read error (-5). The error results if the return value of datetime % strftime("%s") has less than 10 digits.

Automated doc generation with FORD

Current markdown documentation for datetime-fortran is nice but was written by hand. Obviously, this approach worked early on but does not scale with the growth of the project.

The code should be documented in the format that is readable by the amazing FORD.

Can't build tests on win-ifort. Fails on linker with strptime

Hello,

I have been using your library with no problems in unix with gfortran, but time has come to compile things in Windows using ifort.

Compiling the library runs, although some warnings do show up. Compiling the tests fails with

Severity Code Description Project File Line Suppression State
Error error LNK2019: unresolved external symbol strptime referenced in function MOD_DATETIME_mp_STRPTIME datetime.lib(mod_datetime.obj)

I'm a bit stuck, any ideas?

Function that ingests ISO format and returns datetime?

Just a question to make sure. Iโ€™d like to convert a project I work on from its own date time format to using ISO date format. So instead of โ€œ20170607 124500โ€ in a startup file, Iโ€™d love to say โ€œ2017-06-07T12:45:00โ€. I know datetime-fortran can convert a datetime object into an ISO format string, but can it do the opposite? (And I guess similar for durations?)

Or because python-datetime doesnโ€™t (itโ€™s part of dateutil parser) this project might not do so (I.e., time to write fortran-dateutil?)

strptime does not handle errors

When I fed strptime with a wrong time string, it just returns a normal result, but I expect an error report:

type(datetime) time

time = strptime('', '%Y-%m-%dT%H:%M:%SZ')
print *, time%isoformat()

=> 1900-01-00T00:00:00.000

time = strptime('XXX', '%Y-%m-%dT%H:%M:%SZ')
print *, time%isoformat()

=> 1900-01-00T00:00:00.000

time = strptime('2017-01-0 15:30:00Z', '%Y-%m-%dT%H:%M:%SZ')
print *, time%isoformat()

=> 2017-01-00T00:00:00.000

...

Maybe it could set some field of datetime to indicate an invalid status? Say:

time = strptime('XXX', '%Y-%m-%dT%H:%M:%SZ')
if (time%invalid) then
  ...
end if

Empty constructor compilation error with PGI 14.4

I know this is might not be an issue for fort or gfortran ( for sure not an issue - tested) but with 14.4 compiling tests fails:

$ make
s.f90 datetime_tests.f90 -g -O0  -o tests datetime.o
USING: /sb/software/areas/armnssm/ssm-domains-base/tools/dev-tools/code-tools_1.0_all/include/Linux_x86-64/pgi2014/Pre_Compiler_rules
USING: /sb/software/areas/armnssm/ssm-domains-base/tools/dev-tools/code-tools_1.0_all/include/Linux_x86-64/pgi2014/Common_Compiler_rules
Compiler Rules applied for Linux PGI version 14
datetime_tests.f90:
PGF90-F-0155-Empty structure constructor() - type datetime (datetime_tests.f90: 158)
PGF90/x86-64 Linux 14.4-0: compilation aborted
make: *** [tests] Error 2

They say they fixed it in 14.7 (Have no idea if it is true).

Building with autotools (not all libs are copied)

Hello,
and HUGE thanks for your enormous effort. Now datetime operations in FORTRAN have stopped being a nightmare! ๐Ÿ‘ One weird thing I'd like to highlight though. Building with autotools:

./configure --prefix=/path/to/folder
make 
make install

at the make install stage the only datetime_module.mod is actually copied in the destination include folder. That is not enough to link datetime.
Fast solution: manually copy all *.mod files from src/lib to /path/to/folder/include.
The issue is probably OS related. I'm using CentOS7, ifort-19.

num2date produces invalid datetime instance

Reported by Hamid Oloso:

Example program that produces wrong datetime instance when the datetime%day of the input instance is the last day of the month

program testDateTime
    use datetime_module
    implicit none
    type (datetime) :: myDatetime

    myDateTime = datetime(1989, 2, 28, 0, 0, 0, 0)
    print *, num2date(date2num(myDatetime))
end program
ifort -c datetime.f90
ifort -I. testDatetime.f90 datetime.o
./a.out

Output:

1989           3           0           0           0           0         0 
0.000000000000000E+000

Please note how the month is 3 instead of 2 and day is 0 instead of 28.

CMake uses different compiler flags to autotools

Please note that the static library built via CMake is built with different flags compared to when it is built with Autotools.

e.g. Cmake:

/usr/bin/f95   -O3 -DNDEBUG -O3 -Jinclude -c [...]/datetime-fortran.git/src/datetime_module.f90 -o CMakeFiles/datetime.dir/src/datetime_module.f90.o
...
/usr/bin/ar qc lib/libdatetime.a CMakeFiles/datetime.dir/src/datetime_module.f90.o
/usr/bin/ranlib lib/libdatetime.a

e.g. Autotools:

gfortran -c -Wall datetime_module.f90
...
ar ruv libdatetime.a datetime_module.o
ar: `u' modifier ignored since `D' is the default (see `U')
ar: creating libdatetime.a
a - datetime_module.o

Environment:

$ gfortran --version
GNU Fortran (Debian 12.2.0-3) 12.2.0

$ ar --version
GNU ar (GNU Binutils for Debian) 2.39

date2num(num2date()) test and more

Please consider these tests:

    d = datetime(2009, 12, 23,  9,  47, 0)
    print *, d%yearday()
    print *, d
    print *, num2date(date2num(d))


    print *, "num2date tests"
    d = d % now()
    print *, d
    print *, num2date(date2num(d))

First part works fine and d == num2date(date2num(d)) and it is OK since time zone is 0.
But when you create a date time with now timezone is set and that might lead that d /= num2date(date2num(d)). I understand that num2date won't save time zone but you have this test in your tests on a date created with now:

 !---------------------------------------------------------------------
  ! Test date2num and num2date

  a = a % now()
  tests(n) = assert(a == num2date(date2num(a)),&
                    'datetime = num2date(date2num(datetime))')
  n = n+1

It did pass for me yesterday somehow.... Probably it appeared today because I added the loops in addHours and in addMinutes as well..

Cheers

Very strange (possibly compiler) bug with date2num

The patch below introduces one passing and one failing test. This problem occurred with intel 17 but not 15, 16 or 18. It did not happen with gfortran.

diff --git a/src/tests/datetime_tests.f90 b/src/tests/datetime_tests.f90
index 0abb98d..799fadb 100644
--- a/src/tests/datetime_tests.f90
+++ b/src/tests/datetime_tests.f90
@@ -1026,6 +1026,16 @@ SUBROUTINE test_datetime
                     'datetime % utc() == num2date(date2num(datetime)) (now)')
   n = n+1

+  a = datetime(1901,05,1)
+  tests(n) = assert(a == num2date(date2num(a)),&
+                    'datetime == num2date(date2num(datetime)) (weird bug passes)')
+  n = n+1
+
+  a = datetime(1901,05,1,3)
+  tests(n) = assert(a == num2date(date2num(a)),&
+                    'datetime == num2date(date2num(datetime)) (weird bug fails)')
+  n = n+1
+
   ! Test for overflowing month
   a = datetime(2014,11,30,1)
   tests(n) = assert(a == num2date(date2num(a)),&

Intel 14 gives a compiler error

Scanning dependencies of target datetime_tests
[ 88%] Building Fortran object CMakeFiles/datetime_tests.dir/src/tests/datetime_tests.f90.o
/home/599/nah599/more_home/Download/datetime-fortran/src/tests/datetime_tests.f90(1): catastrophic error: **Internal compiler error: internal abort** Please report this error along with the circumstances in which it occurred in a Software Problem Report.  Note: File and line given may not be explicit cause of this error.
compilation aborted for /home/599/nah599/more_home/Download/datetime-fortran/src/tests/datetime_tests.f90 (code 1)
make[2]: *** [CMakeFiles/datetime_tests.dir/src/tests/datetime_tests.f90.o] Error 1
make[1]: *** [CMakeFiles/datetime_tests.dir/all] Error 2
make: *** [all] Error 2

Intel 13 gives a segmentation fault:

test datetime == num2date(date2num(datetime)) (weird bug passes) : PASS
test datetime == num2date(date2num(datetime)) (weird bug fails)  : PASS
test datetime == num2date(date2num(datetime)) (overflowing month): PASS
test datetime == num2date(date2num(datetime)) (overflowing year) : PASS
-----------------------------------------------------------------------
forrtl: severe (174): SIGSEGV, segmentation fault occurred
Image              PC                Routine            Line        Source
datetime_tests     0000000000452820  mod_datetime_mp_e         998  mod_datetime.f90
datetime_tests     000000000043D63D  datetime_tests_mp        1066  datetime_tests.f90
datetime_tests     0000000000448916  MAIN__                   1284  datetime_tests.f90
datetime_tests     000000000040300C  Unknown               Unknown  Unknown
libc.so.6          00002B896DBB1D1D  Unknown               Unknown  Unknown
datetime_tests     0000000000402F09  Unknown               Unknown  Unknown

Processing of `secondsSinceEpoch` and its reverse processing routine.

When I try to get Epoch time using secondsSinceEpoch , results of these values are different from C language's mktime function's results. datetime-fortran calculate epoc time with own routine (secondsSinceEpoch), and don't use time zone information.
So, I fixes to use time zone information to calculate epoc time, and confirmed to be same as C language's mktime function results.
(I believe that secondsSinceEpoch is correct with UTC time zone.)

https://github.com/sakamoti/datetime-fortran

In addition, reverse processing routine (secondsSinceEpoch to type(datetime)) is added to this library with using C language's localtime_r and gmtime_r.

As a result, it would be possible to interconvert between secondsSinceEpoch expressed in int64 and type(datetime) , and it would be easier to work with C and Python.
Furthermore, I believe that the conversion to integer type will enable users to speed up the computation time with their own ingenuity.

My fork repository on the above github souce achieves these things.

I would be happy to be merged these features, but I created this issue here first in case there are better ways or other opinions.

Cannot set seconds or others of timedelta

Code is as following:

time_step_size = timedelta(seconds=time_step_size_in)

and error is:

Error: Component 'seconds' at (1) is a PRIVATE component of 'timedelta'

The Fortran compiler that I am using is gfortran 7.2.0.

Strptime Undefined Reference Error

I get the following error when trying to use the strptime function:

.\obj\test_strptime.o:test_strptime.f90:(.text.startup+0x5d): undefined reference to `__mod_datetime_MOD_strptime'
.\obj\test_strptime.o:test_strptime.f90:(.text.startup+0xdf): undefined reference to `__mod_datetime_MOD_strptime'
collect2.exe: error: ld returned 1 exit status

I'm trying to use the public strptime function like follows:

program teststrptime

use datetime_module

type(datetime)  :: date1,date2
type(timedelta) :: timediff

! Example times in "YYYYMMDD hhmmss" format
character(len=15) :: str1 = "20130512 091519"
character(len=15) :: str2 = "20131116 120418"

date1 = strptime(str1,"%Y%m%d %H%M%S")
date2 = strptime(str2,"%Y%m%d %H%M%S")

timediff = date2-date1

!write(*,*)timediff
!write(*,*)timediff%total_seconds()

end program teststrptime

I am using gfortran GCC 6.3.0 from MinGW on Windows. I have the datetime-fortran library in a lib folder and the mod files in a include folder. I'm compiling like so:

gfortran -O2 -fbacktrace -c test_strptime.f90 -o .\obj\test_strptime.o -L./lib -ldatetime -I./include/ -I./obj -J./obj
gfortran -O2 -fbacktrace -o teststrptime .\obj\test_strptime.o

Using date2num instead of using strptime does not cause an error during compiling.

Any suggestions would be appreciated. I'm still fairly new at linking libraries for Fortran development.

Installation

I am interested in packaging datetime-fortran for Arch.

It would be useful if the Makefile had an 'install' rule, and a 'pc' file that would allow library locations to be picked up "automagically". I am more than willing to supply patches if you're ammenable to the idea, and we can reach a solution that is acceptable to both of us.

Please let me know if you're interested.

Archiving/distributing

The following issues were noted upon releasing 1.4.0:

@milancurcic said "make dist failed to install CONTRIBUTORS, README.md and LICENSE."

My response: I agree. I will look into this.

@zbeekman said "If you can find a way to get make dist to package the missing markdown files, you can just manually add the tarball generated by make dist as a release asset."

Yes. I think it is easy enough for me to do this.

I note additional packaging problems:

  • git creates archives based on what is checked into the repo, which unfortunately does not include configure
  • there can be mismatches between the version numbers in tags, the configure.ac file, and what's in src/lib/datetime.f90

I will look into these issues. If anyone has a good anser to this, then let me know.

logical comparision error

Line 1410 needs to be changed from

IF(self%stopped == .TRUE.)THEN

to

IF(self%stopped .EQV. .TRUE.)THEN

because logicals must be compared with .eqv. instead of ==

gives gfortran 4.8.1 error

strptime does not zero tm struct before calling c_strptime

man strptime gives an example code like the below:

   int
       main(void)
       {
           struct tm tm;
           char buf[255];

           memset(&tm, 0, sizeof(struct tm));
           strptime("2001-11-12 18:31:01", "%Y-%m-%d %H:%M:%S", &tm);
           strftime(buf, sizeof(buf), "%d %b %Y %H:%M", &tm);
           puts(buf);
           exit(EXIT_SUCCESS);
       }

The tm struct is zeroed before calling. datetime-fortran strptime does not do this which means that depending on the time string/format parts of the tm struct can be left containing uninitialised values.

Some cygwin/gfortran 4.9.3 test fails

Here are the test results for gfortran 4.9.3 on cygwin using v1.4.0:

test empty datetime() constructor                                : FAIL
test semi-empty datetime() constructor                           : FAIL
test datetime + timedelta(milliseconds = 100)                    : FAIL
test datetime + timedelta(milliseconds = -100)                   : FAIL
test datetime + timedelta(seconds = 1)                           : FAIL
test datetime + timedelta(seconds = -1)                          : FAIL
test datetime + timedelta(minutes = 1)                           : FAIL
test datetime + timedelta(minutes = -1)                          : FAIL
test datetime + timedelta(hours = 1)                             : FAIL
test datetime + timedelta(hours = -1)                            : FAIL
test datetime + timedelta(days = 1)                              : FAIL
test datetime + timedelta(days = -1)                             : FAIL
test Seconds overflow in addMilliseconds (3000 milliseconds)     : FAIL
test Seconds overflow in addMilliseconds (-3000 milliseconds)    : FAIL
test Minutes overflow in addSeconds (360 seconds)                : FAIL
test Minutes overflow in addSeconds (-360 seconds)               : FAIL
test Hours overflow in addMinutes (360 minutes)                  : FAIL
test Hours overflow in addMinutes (-360 minutes)                 : FAIL
test Days overflow in addHours (72 hours)                        : FAIL
test Days overflow in addHours (-72 hours)                       : FAIL
-----------------------------------------------------------------------
test decrement datetime into January                             : FAIL
test decrement datetime into February                            : FAIL
test decrement datetime into March                               : FAIL
test decrement datetime into April                               : FAIL
test decrement datetime into May                                 : FAIL
test decrement datetime into June                                : FAIL
test decrement datetime into July                                : FAIL
test decrement datetime into August                              : FAIL
test decrement datetime into September                           : FAIL
test decrement datetime into October                             : FAIL
test decrement datetime into November                            : FAIL
test decrement datetime into December                            : FAIL
-----------------------------------------------------------------------
test datetime-datetime == timedelta(days = 1)                    : FAIL
test datetime-datetime == timedelta(hours = 1)                   : FAIL
test datetime-datetime == timedelta(minutes = 1)                 : FAIL
test datetime-datetime == timedelta(seconds = 1)                 : FAIL
test datetime-datetime == timedelta(milliseconds = 1)            : FAIL
-----------------------------------------------------------------------
test datetime == datetime                                        : FAIL
test datetime == datetime, timezone test 1                       : FAIL
test datetime == datetime, timezone test 2                       : FAIL
test datetime /= datetime                                        : PASS
test datetime > datetime                                         : FAIL
test datetime >= datetime (greater)                              : FAIL
test datetime >= datetime (equal)                                : FAIL
test datetime < datetime                                         : PASS
test datetime <= datetime (less)                                 : PASS
test datetime <= datetime (equal)                                : PASS
-----------------------------------------------------------------------
test datetime % isoformat, default separator                     : PASS
test datetime % isoformat, T separator                           : PASS
test datetime % isoformat, blank separator                       : PASS
-----------------------------------------------------------------------
test datetime % strftime                                         : PASS
test datetime % strptime                                         : FAIL
test strptime(datetime % strftime(fmt),fmt) == datetime          : FAIL
-----------------------------------------------------------------------
test datetime(2005,1,1) % isocalendar() == [2004,53,6]           : PASS
test datetime(2005,1,2) % isocalendar() == [2004,53,7]           : PASS
test datetime(2005,12,31) % isocalendar() == [2005,52,6]         : PASS
test datetime(2007,1,1) % isocalendar() == [2007,1,1]            : PASS
test datetime(2007,12,30) % isocalendar() == [2007,52,7]         : PASS
test datetime(2007,12,31) % isocalendar() == [2008,1,1]          : PASS
test datetime(2008,1,1) % isocalendar() == [2008,1,2]            : PASS
test datetime(2008,12,28) % isocalendar() == [2008,52,7]         : PASS
test datetime(2008,12,29) % isocalendar() == [2009,1,1]          : PASS
test datetime(2008,12,30) % isocalendar() == [2009,1,2]          : PASS
test datetime(2008,12,31) % isocalendar() == [2009,1,3]          : PASS
test datetime(2009,1,1) % isocalendar() == [2009,1,4]            : PASS
test datetime(2009,12,31) % isocalendar() == [2009,53,4]         : PASS
test datetime(2010,1,1) % isocalendar() == [2009,53,5]           : PASS
test datetime(2010,1,2) % isocalendar() == [2009,53,6]           : PASS
test datetime(2010,1,3) % isocalendar() == [2009,53,7]           : PASS
-----------------------------------------------------------------------
test datetime(1,1,1) is valid                                    : PASS
test datetime(0,1,1) is not valid                                : PASS
test datetime(-1,1,1) is not valid                               : PASS
test datetime(2014,1,1) is valid                                 : PASS
test datetime(2014,0,1) is not valid                             : PASS
test datetime(2014,1,0) is not valid                             : PASS
test datetime(2014,2,28) is valid                                : PASS
test datetime(2014,2,29) is not valid                            : PASS
test datetime(2012,2,29) is valid                                : PASS
test datetime(2012,3,31) is valid                                : PASS
test datetime(2012,3,32) is not valid                            : PASS
test datetime(2012,3,31,0,0,0) is valid                          : PASS
test datetime(2012,3,31,24,0,0) is not valid                     : PASS
test datetime(2012,3,31,0,60,0) is not valid                     : PASS
test datetime(2012,3,31,0,0,60) is not valid                     : PASS
test datetime(2012,3,31,0,0,0,1000) is not valid                 : PASS
-----------------------------------------------------------------------
test datetime % secondsSinceEpoch(), 0 seconds                   : PASS
test datetime % secondsSinceEpoch(), 1 hour                      : PASS
test datetime % secondsSinceEpoch(), -1 hour                     : PASS
-----------------------------------------------------------------------
test datetime % tzOffset(), +0000                                : PASS
test datetime % tzOffset(), -0330                                : PASS
test datetime % tzOffset(), +0545                                : PASS
-----------------------------------------------------------------------
test datetime % utc(), +0000                                     : FAIL
-----------------------------------------------------------------------
test datetime % weekday(), Wednesday                             : PASS
test datetime % weekday(), Thursday                              : PASS
test datetime % weekday(), Friday                                : PASS
test datetime % weekday(), Saturday                              : PASS
test datetime % weekday(), Sunday                                : PASS
test datetime % weekday(), Monday                                : PASS
test datetime % weekday(), Tuesday                               : PASS
-----------------------------------------------------------------------
test datetime % weekdayLong(), Wednesday                         : PASS
test datetime % weekdayLong(), Thursday                          : PASS
test datetime % weekdayLong(), Friday                            : PASS
test datetime % weekdayLong(), Saturday                          : PASS
test datetime % weekdayLong(), Sunday                            : PASS
test datetime % weekdayLong(), Monday                            : PASS
test datetime % weekdayLong(), Tuesday                           : PASS
-----------------------------------------------------------------------
test datetime % weekdayShort(), Wed                              : PASS
test datetime % weekdayShort(), Thu                              : PASS
test datetime % weekdayShort(), Fri                              : PASS
test datetime % weekdayShort(), Sat                              : PASS
test datetime % weekdayShort(), Sun                              : PASS
test datetime % weekdayShort(), Mon                              : PASS
test datetime % weekdayShort(), Tue                              : PASS
-----------------------------------------------------------------------
test datetime(2014,1,1) % yearday() == 1                         : PASS
test datetime(2014,2,1) % yearday() == 32                        : PASS
test datetime(2014,3,1) % yearday() == 60                        : PASS
test datetime(2014,4,1) % yearday() == 91                        : PASS
test datetime(2014,5,1) % yearday() == 121                       : PASS
test datetime(2014,6,1) % yearday() == 152                       : PASS
test datetime(2014,7,1) % yearday() == 182                       : PASS
test datetime(2014,8,1) % yearday() == 213                       : PASS
test datetime(2014,9,1) % yearday() == 244                       : PASS
test datetime(2014,10,1) % yearday() == 275                      : PASS
test datetime(2014,11,1) % yearday() == 305                      : PASS
test datetime(2014,12,1) % yearday() == 335                      : PASS
-----------------------------------------------------------------------
test timedelta empty constructor                                 : PASS
test timedelta % total_seconds(), milliseconds conversion        : PASS
test timedelta % total_seconds(), seconds conversion             : PASS
test timedelta % total_seconds(), minutes conversion             : PASS
test timedelta % total_seconds(), hours conversion               : PASS
test timedelta % total_seconds(), days conversion                : PASS
-----------------------------------------------------------------------
test datetime % utc() == num2date(date2num(datetime)) (now)      : FAIL
test datetime == num2date(date2num(datetime)) (overflowing month): FAIL
test datetime == num2date(date2num(datetime)) (overflowing year) : FAIL
-----------------------------------------------------------------------
test datetimeRange, day increment                                : PASS
test datetimeRange, hour increment                               : FAIL
test datetimeRange, minute increment                             : FAIL
test datetimeRange, second increment                             : FAIL
test datetimeRange, rounding test                                : FAIL
-----------------------------------------------------------------------
test isLeapYear(1) == F                                          : PASS
test isLeapYear(4) == T                                          : PASS
test isLeapYear(100) == F                                        : PASS
test isLeapYear(400) == T                                        : PASS
test isLeapYear(2000) == T                                       : PASS
test isLeapYear(2014) == F                                       : PASS
-----------------------------------------------------------------------
test daysInYear(2014) == 365                                     : PASS
test daysInYear(2012) == 366                                     : PASS
test daysInYear(2000) == 366                                     : PASS
test daysInYear(1900) == 365                                     : PASS
-----------------------------------------------------------------------
test daysInMonth(1,2014) == 31                                   : PASS
test daysInMonth(2,2014) == 28                                   : PASS
test daysInMonth(2,2012) == 29                                   : PASS
test daysInMonth(3,2014) == 31                                   : PASS
test daysInMonth(4,2014) == 30                                   : PASS
test daysInMonth(5,2014) == 31                                   : PASS
test daysInMonth(6,2014) == 30                                   : PASS
test daysInMonth(7,2014) == 31                                   : PASS
test daysInMonth(8,2014) == 31                                   : PASS
test daysInMonth(9,2014) == 30                                   : PASS
test daysInMonth(10,2014) == 31                                  : PASS
test daysInMonth(11,2014) == 30                                  : PASS
test daysInMonth(12,2014) == 31                                  : PASS
-----------------------------------------------------------------------
test clock % started == F (before tick)                          : PASS
test clock % started == T (after 1 tick)                         : PASS
test clock % stopped == F (after 1 tick)                         : FAIL
test clock % currentTime == clock % stopTime (after 24 ticks)    : FAIL
test clock % stopped == T (after 24 ticks)                       : PASS
test clock % started == F (after reset)                          : PASS
test clock % stopped == F (after reset)                          : PASS
test clock % currentTime == clock % startTime (after reset)      : FAIL
-----------------------------------------------------------------------
Ran a total of 170 tests.
114 tests PASSED,  56 tests FAILED.

incorrect literal with REAL64 kind

The statement below (and similar ones) are incorrect:

real(kind=real64),parameter :: d2s = 86400_real64

the reason being is that 86400 is an integer literal, and the REAL64 kind is for real types. This might work if the REAL64 kind is the same as integer kinds, but will not work otherwise. The safe option is to convert it to real, i.e.

real(kind=real64),parameter :: d2s = 86400.0_real64

I came across this when trying to build it with the NAG Fortran compiler. Might be worth building it with the NAG compiler to catch any other potential bugs.

Cheers,
Wadud.

Division by zero in datetime%utc()

Reported and fixed by Bjoern Hendrik Fock of University of Hamburg.

Problem: Calling datetime%utc() with a datetime instance that is already in UTC timezone (i.e. datetime%tz = 0) resulted in a division by zero.

Solution: Replacing the problematic line that uses division with a line that uses the intrinsic SIGN() function solves the problem.

datetime and timedelta constructor validation

datetime and timedelta contructor function currently do not implement and validation of input arguments to the contructor. For example, the datetime contructor needs to validate the following:

  • Is year > 0?
  • Is 0 < month < 13?
  • Is 0 < day < 32?
  • etc.

and raise an exception if any of the above tests fail. Similarly for timedelta constructor.

Currently, these constructors are implemented as pure elemental functions which allows the user to instantiate an array of datetimes or timedeltas in a familiar Fortran array syntax. Once the above validations and raising exceptions are implemented, these functions cannot be pure (nor elemental) anymore, because only an impure procedure can write to standard output and stop the program. Consequently, this will require implementing a separate version of constructors that will accept arrays as actual arguments, and which will be used for overloading the contructor.

Compilation error

Hi I am trying to compile the datetime.f90, but getting this error message, do you know what is wrong?

PGF90-F-0155-No default initialization in structure constructor- member yearday$tbp$0 (datetime.f90: 229)

The compiler is pgf95. Compilation command is:

pgf95 -c .... -Mreentrant -Miomutex -byteswapio -I. -tp nehalem-64 -mcmodel=medium -Bdynamic -O0 -V -Mbounds   -g -Ktrap=fp  datetime.f90

Thanks

Bug in datetime arithmetic when subtracting hours?

I have run into some odd behaviour when I perform datetime arithmetic using a negative timedelta. This issue only seems to occur when the subtraction causes a change in month.

Basically, I want to subtract six hours from a date, but when I do this on the first of the month at 00:00 time, I get incorrect results for some months. Consider the following code:

      PROGRAM datetime_test

      USE DATETIME_MODULE

      TYPE(datetime)   :: date, date2
      INTEGER          :: m

      DO m=1,12
         date = DATETIME(2013,m,1,0,0,0,0) ! First of month
         date2 = date + timedelta(hours=-6)
         PRINT*, date%isoformat(), " -6hrs = ",date2%isoformat()
      enddo

      END PROGRAM datetime_test

This is the output:

 2013-01-01T00:00:00.000 -6hrs = 2012-12-31T18:00:00.000
 2013-02-01T00:00:00.000 -6hrs = 2013-01-28T18:00:00.000 
 2013-03-01T00:00:00.000 -6hrs = 2013-03-03T18:00:00.000 !! WRONG!
 2013-04-01T00:00:00.000 -6hrs = 2013-03-30T18:00:00.000
 2013-05-01T00:00:00.000 -6hrs = 2013-05-01T18:00:00.000 !! WRONG!
 2013-06-01T00:00:00.000 -6hrs = 2013-05-30T18:00:00.000
 2013-07-01T00:00:00.000 -6hrs = 2013-07-01T18:00:00.000 !! WRONG!
 2013-08-01T00:00:00.000 -6hrs = 2013-07-31T18:00:00.000
 2013-09-01T00:00:00.000 -6hrs = 2013-08-30T18:00:00.000
 2013-10-01T00:00:00.000 -6hrs = 2013-10-01T18:00:00.000 !! WRONG!
 2013-11-01T00:00:00.000 -6hrs = 2013-10-30T18:00:00.000
 2013-12-01T00:00:00.000 -6hrs = 2013-12-01T18:00:00.000

The results for March, May, July and October are incorrect: the hour is correct, but the day and month has not changed.

Timezone handling

datetime-fortran currently provides no timezone information in the datetime class definition. I believe timezone handling should be implemented as an optional derived type which is a component of datetime:

TYPE :: datetime

    ...

    TYPE :: tz
        ! tz components
    ENDTYPE tz

ENDTYPE datetime

A possible timezone model may the one from Python: http://docs.python.org/2/library/datetime.html#tzinfo-objects

Debugging code that uses date time module

Hi:

This is more a question than an issue. I have trouble debugging code that uses the date time module.
With ddt, compiled with pgi:
whenever I get in the code where manipulations with date time objects occur (maybe reference to fields...), the gdb process starts consuming enormous amount of memory and it consumes it all...

With gdb-apple compiled with gfortran:
eclipse is refusing to show the datetime or timedelta objects (ddt shows the objects but it freezes due to memory issues)

screen shot 2014-10-01 at 10 00 27

Do you think it is possible to change the type definitions to make them more debugger friendly?

Cheers

Dealing with huge timedelta values

Hello,
Once again thank you for this saving life lib!

I have to deal with datasets where time is written as, say, "seconds since 1900-01-01 ...". In order to convert any modern date into this format, I need to subtract 1900-01-01 from it and than convert into seconds using total_seconds. Obviously. But the total_seconds function becomes crazy if the number of days exceeds 68 years. It happens because privates in timedelta (days,hours,etc) are integer(4) by default and hence in total_seconds self % days*86400=68x365x86400 seconds exceeds HUGE(integer(4)):

  total_seconds = self % days*86400 + self % hours*3600&
                + self % minutes*60 + self % seconds   &
                + self % milliseconds*1e-3_real64

Fast check:

program test
use datetime_module
implicit none

type(datetime)  :: a,b
type(timedelta) :: c
integer :: ii

    ! print*,"Setting a very long period (approx. 63 to 74 year)"
    do ii = 23000, 27000, 100
         c = timedelta(days=ii)
         print*,ii,c%total_seconds()
     end do

end program test

Fast and rough cure: recompile the datetime-fortran lib using integer(8) by default. For Intel Compiler it would look like this:

FC=ifort FCFLAGS='-g -i8' ./configure --prefix=/path/to/folder 
make 
make install

It did the trick for me.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.