# datetime-fortran
Date and time manipulation for modern Fortran.
The fundamental time step is one millisecond.
## Getting started
Get the pro.
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](https://github.com/fortran-lang/fpm).
Follow the directions on that page to install FPM if you haven't already.
To build, type:
```sh
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:
```sh
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
```sh
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):
```sh
cmake -B build -DCMAKE_INSTALL_PREFIX=~/mylibs
cmake --install build
```
optionally, to run self-tests:
```sh
cd build
ctest -V
```
## Use
Start using datetime-fortran in your code by importing derived types from the module:
```fortran
use datetime_module, only: datetime, timedelta, clock
```
See some basic examples [here](examples).
<a id="top"></a>
## API
* [Derived Types](#derived-types)
* [*datetime*](#datetime)
* [*getYear*](#getyear)
* [*getMonth*](#getmonth)
* [*getDay*](#getday)
* [*getHour*](#gethour)
* [*getMinute*](#getminute)
* [*getSecond*](#getsecond)
* [*getMillisecond*](#getmillisecond)
* [*isocalendar*](#isocalendar)
* [*isoformat*](#isoformat)
* [*isValid*](#isvalid)
* [*now*](#now)
* [*secondsSinceEpoch*](#secondssinceepoch)
* [*strftime*](#strftime)
* [*tm*](#tm)
* [*tzOffset*](#tzoffset)
* [*utc*](#utc)
* [*weekday*](#weekday)
* [*weekdayLong*](#weekdaylong)
* [*weekdayShort*](#weekdayshort)
* [*yearday*](#yearday)
* [*timedelta*](#timedelta)
* [*total_seconds*](#total_seconds)
* [*clock*](#clock)
* [*reset*](#reset)
* [*tick*](#tick)
* [*tm_struct*](#tm_struct)
* [Overloaded operators](#overloaded-operators)
* [Arithmetic operators](#arithmetic-operators)
* [Comparison operators](#comparison-operators)
* [Public procedures](#public-procedures)
* [*c_strftime*](#c_strftime)
* [*c_strptime*](#c_strptime)
* [*date2num*](#date2num)
* [*datetimeRange*](#datetimerange)
* [*daysInMonth*](#daysinmonth)
* [*daysInYear*](#daysinyear)
* [*isLeapYear*](#isleapyear)
* [*num2date*](#num2date)
* [*strptime*](#strptime)
* [*tm2date*](#tm2date)
* [*machinetimezone*](#machinetimezone)
* [*epochdatetime*](#epochdatetime)
* [*localtime*](#localtime)
* [*gmtime*](#gmtime)
## Derived Types<a id="derived-types"></a>
*datetime-fortran* library provides the following derived types:
[*datetime*](#datetime), [*timedelta*](#timedelta),
[*clock*](#clock) and [*tm_struct*](#tm_struct).
### datetime <a id="datetime"></a>
Main date and time object, defined as:
```fortran
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*](#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
```fortran
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*](#datetime)
does not support daylight saving time (DST) information.
#### See also
* [*timedelta*](#timedelta)
* [*tm_struct*](#tm_struct)
[Back to top](#top)
<hr>
### getYear<a id="getyear"></a>
```fortran
pure elemental integer function getYear(self)
class(datetime),intent(in) :: self
```
Returns the year of a `datetime` instance.
[Back to top](#top)
<hr>
### getMonth<a id="getmonth"></a>
```fortran
pure elemental integer function getMonth(self)
class(datetime),intent(in) :: self
```
Returns the month of a `datetime` instance.
[Back to top](#top)
<hr>
### getDay<a id="getday"></a>
```fortran
pure elemental integer function getDay(self)
class(datetim