Module datetime | Tarantool

Module datetime

Since: 2.10.0

The datetime module provides support for the datetime data types. It allows creating the date and time values either via the object interface or via parsing string values conforming to the ISO-8601 standard.

Below is a list of datetime functions, properties, and related objects.

Functions  
datetime.new() Create an object of the datetime type from a table of time units
datetime.now() Create an object of the datetime type with the current date and time
datetime.is_datetime() Check whether the specified value is a datetime object
datetime.parse() Convert an input string with the date and time information into a datetime object
datetime.interval.is_interval() Check whether the specified value is an interval object
datetime.interval.new() Create an object of the interval type from a table of time units
Properties  
datetime.TZ A Lua table that maps timezone names and abbreviations to its index and vice-versa.
Methods  
datetime_object:add() Modify an existing datetime object by adding values of the input argument
datetime_object:format() Convert the standard datetime object presentation into a formatted string
datetime_object:set() Update the field values in the existing datetime object
datetime_object:sub() Modify an existing datetime object by subtracting values of the input argument
datetime_object:totable() Convert the information from a datetime object into the table format
interval_object:totable() Convert the information from an interval object into the table format

datetime.new([{ units }])

Create an object of the datetime type from a table of time units. See the description of units and examples below.

Parameters:
  • units (table) – Table of time units. If an empty table or no arguments are passed, the datetime object with the default values corresponding to Unix Epoch is created: 1970-01-01T00:00:00Z.
Return:

datetime object

Rtype:

cdata

Possible input time units for datetime.new()

Name Description Type Default
nsec (usec, msec) Fractional part of the last second. You can specify either nanoseconds (nsec), or microseconds (usec), or milliseconds (msec). Specifying two of these units simultaneously or all three ones lead to an error. number 0
sec Seconds. Value range: 0 - 60. A leap second is supported, see a section leap second. number 0
min Minutes. Value range: 0 - 59. number 0
hour Hours. Value range: 0 - 23. number 0
day Day number. Value range: 1 - 31. The special value -1 generates the last day of a particular month (see example below). number 1
month Month number. Value range: 1 - 12. number 1
year Year. number 1970
timestamp Timestamp, in seconds. Similar to the Unix timestamp, but can have a fractional part that is converted in nanoseconds in the resulting datetime object. If the fractional part for the last second is set via the nsec, usec, or msec units, the timestamp value should be integer otherwise an error occurs. The timestamp is not allowed if you already set time and/or date via specific units, namely, sec, min, hour, day, month, and year. number 0
tzoffset A time zone offset from UTC, in minutes. Value range: -720 - 840 inclusive. If both tzoffset and tz are specified, tz has the preference and the tzoffset value is ignored. See a section timezone. number 0
tz A time zone name according to the Time Zone Database. See the Time zones section. string

Examples:

tarantool> datetime.new {
            nsec = 123456789,

            sec = 20,
            min = 25,
            hour = 18,

            day = 20,
            month = 8,
            year = 2021,

            tzoffset  = 180
            }
---
- 2021-08-20T18:25:20.123456789+0300
...

tarantool> datetime.new {
            nsec = 123456789,

            sec = 20,
            min = 25,
            hour = 18,

            day = 20,
            month = 8,
            year = 2021,

            tzoffset = 60,
            tz = 'Europe/Moscow'
            }
---
- 2021-08-20T18:25:20.123456789 Europe/Moscow
...

tarantool> datetime.new {
            day = -1,
            month = 2,
            year = 2021,
            }
---
- 2021-02-28T00:00:00Z
...

tarantool> datetime.new {
            timestamp = 1656664205.123,
            tz = 'Europe/Moscow'
            }
---
- 2022-07-01T08:30:05.122999906 Europe/Moscow
...

tarantool> datetime.new {
            nsec = 123,
            timestamp = 1656664205,
            tz = 'Europe/Moscow'
            }
---
- 2022-07-01T08:30:05.000000123 Europe/Moscow
...
datetime.now()

Create an object of the datetime type with the current date and time.

Return:datetime object
Rtype:cdata
datetime.is_datetime([value])

Check whether the specified value is a datetime object.

Parameters:
  • value (any) – the value to check
Return:

true if the specified value is a datetime object; otherwise, false

Rtype:

boolean

datetime.parse('input_string'[, {format, tzoffset}])

Convert an input string with the date and time information into a datetime object. The input string should be formatted according to one of the following standards:

  • ISO 8601
  • RFC 3339
  • extended strftime – see description of the format() for details.

By default fields that are not specified are equal to appropriate values in a Unix time.

Leap second is supported, see a section leap second.

Parameters:
  • input_string (string) – string with the date and time information.
  • format (string) – indicator of the input_string format. Possible values: ‘iso8601’, ‘rfc3339’, or strptime-like format string. If no value is set, the default formatting is used ("%F %T %Z"). Note that only a part of possible ISO 8601 and RFC 3339 formats are supported. To parse unsupported formats, you can specify a format string manually using conversion specifications and ordinary characters.
  • tzoffset (number) – time zone offset from UTC, in minutes.
Return:

a datetime_object

Rtype:

cdata

Return:

a number of parsed characters

Rtype:

number

Example:

tarantool> datetime.parse('1970-01-01T00:00:00Z')
---
- 1970-01-01T00:00:00Z
- 20
...

tarantool> t = datetime.parse('1970-01-01T00:00:00', {format = 'iso8601', tzoffset = 180})

tarantool> t
---
- 1970-01-01T00:00:00+0300
...

tarantool> t = datetime.parse('2017-12-27T18:45:32.999999-05:00', {format = 'rfc3339'})

tarantool> t
---
- 2017-12-27T18:45:32.999999-0500
...

tarantool> T = datetime.parse('Thu Jan  1 03:00:00 1970', {format = '%c'})

tarantool> T
---
- 1970-01-01T03:00:00Z
...

tarantool> T = datetime.parse('12/31/2020', {format = '%m/%d/%y'})

tarantool> T
---
- 2020-12-31T00:00:00Z
...

tarantool> T = datetime.parse('1970-01-01T03:00:00.125000000+0300', {format = '%FT%T.%f%z'})

tarantool> T
---
- 1970-01-01T03:00:00.125+0300
...

tarantool> dt = datetime.parse('01:01:01 MSK', {format ='%H:%M:%S %Z'})

---
...

tarantool> dt.year
---
- 1970
...

tarantool> dt.month
---
- 1
...

tarantool> dt.wday
---
- 5
...

tarantool> dt.tz
---
- MSK
...
datetime.interval.is_interval([value])

Since: 3.2.0

Check whether the specified value is an interval object.

Parameters:
  • value (any) – the value to check
Return:

true if the specified value is an interval object; otherwise, false

Rtype:

boolean

Examples:

If a numeric value is passed to is_interval(), it returns false:

tarantool> datetime = require('datetime')
---
...
tarantool> datetime.interval.is_interval(123)
---
- false
...

If an interval object is passed to is_interval(), it returns true:

tarantool> datetime.interval.is_interval(datetime.interval.new())
---
- true
...
datetime.interval.new()

Create an object of the interval type from a table of time units. See description of units and examples below.

Parameters:
  • input (table) – Table with time units and parameters. For all possible time units, the values are not restricted. If an empty table or no arguments are passed, the interval object with the default value 0 seconds is created.
Return:

interval_object

Rtype:

cdata

Possible input time units and parameters for datetime.interval.new()

Name Description Type Default
nsec (usec, msec) Fractional part of the last second. You can specify either nanoseconds (nsec), or microseconds (usec), or milliseconds (msec). Specifying two of these units simultaneously or all three ones lead to an error. number 0
sec Seconds number 0
min Minutes number 0
hour Hours number 0
day Day number number 0
week Week number number 0
month Month number number 0
year Year number 0
adjust Defines how to round days in a month after an arithmetic operation. string ‘none’

Examples:

tarantool> datetime.interval.new()

---
- 0 seconds
...

tarantool> datetime.interval.new {
            month = 6,
            year = 1
            }
---
- +1 years, 6 months
...

tarantool> datetime.interval.new {
            day = -1
            }
---
- -1 days
...

TZ

Since: 2.11.0

A Lua table that maps timezone names (like Europe/Moscow) and timezone abbreviations (like MSK) to its index and vice-versa. See the Time zones section.

tarantool> datetime.TZ['Europe/Moscow']
---
- 947
...

tarantool> datetime.TZ[947]
---
- Europe/Moscow
...

The datetime module enables creating of objects of two types: datetime and interval.

If you need to shift the datetime object values, you can use either the modifier methods, that is, the datetime_object:add() or datetime_object:sub() methods, or apply interval arithmetic using overloaded + (__add) or - (__sub) methods.

datetime_object:add()/datetime_object:sub() modify the current object, but +/- create copy of the object as the operation result.

In the interval operation, each of the interval subcomponents is sequentially calculated starting from the largest (year) to the smallest (nsec):

  • year – years
  • month – months
  • week – weeks
  • day – days
  • hour – hours
  • min – minutes
  • sec – seconds
  • nsec – nanoseconds

If the results of the operation exceed the allowed range for any of the components, an exception is raised.

The datetime and interval objects can participate in arithmetic operations:

  • The sum of two intervals is an interval object, whose fields are the sum of each particular component of operands.
  • The result of subtraction of two intervals is similar: it’s an interval object where each subcomponent is the result of subtraction of particular fields in the original operands.
  • If you add datetime and interval objects, the result is a datetime object. The addition is performed in a determined order from the largest component (year) to the smallest (nsec).
  • Subtraction of two datetime objects produces an interval object. The difference of two time values is performed not as the difference of the epoch seconds, but as difference of all the subcomponents, that is, years, months, days, hours, minutes, and seconds.
  • An untyped table object can be used in each context where the typed datetime or interval objects are used if the left operand is a typed object with an overloaded operation of + or -.

The matrix of the addition operands eligibility and their result types:

  datetime interval table
datetime unsupported datetime datetime
interval datetime interval interval

The matrix of the subtraction operands eligibility and their result types:

  datetime interval table
datetime interval datetime datetime
interval unsupported interval interval

The subtraction and addition of datetime objects are performed taking tzdata into account tzoffset or tz fields are set:

tarantool> datetime.new({tz='MSK'}) - datetime.new({tz='UTC'})
---
- -180 minutes
...

If you need to compare the datetime and interval object values, you can use standard Lua relational operators: ==, ~=, >, <, >=, and <=. These operators use the overloaded __eq, __lt, and __le metamethods to compare values.

Support for relational operators for interval objects has been added since 2.11.0.

Example 1:

tarantool> dt1 = datetime.new({ year = 2010 })
---
...

tarantool> dt2 = datetime.new({ year = 2024 })
---
...

tarantool> dt1 == dt2
---
- false
...

tarantool> dt1 < dt2
---
- true
...

Example 2:

tarantool> iv1 = datetime.interval.new({month = 1})
---
...

tarantool> iv2 = datetime.interval.new({month = 2})
---
...

tarantool> iv1 < iv2
---
- true
...

Leap seconds are a periodic one-second adjustment of Coordinated Universal Time(UTC) in order to keep a system’s time of day close to the mean solar time. However, the Earth’s rotation speed varies in response to climatic and geological events, and due to this, UTC leap seconds are irregularly spaced and unpredictable.

Tarantool includes the Time Zone Database that besides the time zone description files also contains a leapseconds file. You can use the Lua module tarantool to get a used version of tzdata.

This section describes how the datetime module supports leap seconds:

  • The function datetime.parse() correctly parses an input string with 60 seconds:

    tarantool> datetime.parse('23:12:60', {format ='%H:%M:%S'})
    ---
    - 1970-01-01T23:13:00Z
    - 8
    ...
    
  • The datetime.new() function and the datetime_object:set() method accept a table with the sec key set to 60 seconds:

    tarantool> datetime.new({ sec = 60 })
    ---
    - 1970-01-01T00:01:00Z
    ...
    

Full support has been added since 2.11.0.

Tarantool uses the Time Zone Database (also known as the Olson database and supported by IANA) for timezone support. You can use the Lua module tarantool to get a used version of tzdata.

Every datetime object has three fields that represent timezone support: tz, tzoffset, and isdst:

  • The field isdst is calculated using tzindex and attributes of the selected timezone in the Olson DB timezone.

    tarantool> require('datetime').parse('2004-06-01T00:00 Europe/Moscow').isdst
    ---
    - true
    ...
    
  • The field tz field can be set to a timezone name or abbreviation. A timezone name is a human-readable name based on the Time Zone Database, for example, “Europe/Moscow”. Timezone abbreviations represent time zones by alphabetic abbreviations such as “EST”, “WST”, and “F”. Both timezone names and abbreviations are available via the bidirectional array datetime.TZ.

  • The field tzoffset is calculated automatically using the current Olson rule. This means that it takes into account summer time, leap year, and leap seconds information when a timezone name is set. However, the tzoffset field can be set manually when an appropriate timezone is not available.

The fields tz and tzoffset can be set in datetime.new(), datetime.parse(), and datetime_object:set(). The arithmetic on datetime objects are performed taking tzdata into account, when tzoffset or tz fields are set, see the Datetime and interval arithmetic section.

  • The supported date range is from -5879610-06-22 to +5879611-07-11.

  • There were moments in past history when local mean time in some particular zone used a timezone offset not representable in a whole minutes but rather in seconds. For example, in Moscow before 1918 there used to be offset +2 hours 31 minutes and 19 seconds. See an Olson dump for this period:

    $ zdump -c1880,1918 -i Europe/Moscow
    
    TZ="Europe/Moscow"
    -       -       +023017 MMT
    1916-07-03      00:01:02        +023119 MMT
    1917-07-02      00      +033119 MST     1
    1917-12-27      23      +023119 MMT
    

    Modern tzdata rules do not use such a tiny fraction, and all timezones differ from UTC in units measured in minutes, not seconds. Tarantool datetime module uses minutes internally as units for tzoffset. So there might be some loss of precision if you try to operate with such ancient timestamps.

Found what you were looking for?
Feedback