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, thedatetime
object with the default values corresponding to Unix Epoch is created:1970-01-01T00:00:00Z
.
Return: 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 thensec
,usec
, ormsec
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
, andyear
.number 0 tzoffset A time zone offset from UTC, in minutes. Value range: -720 - 840 inclusive. If both tzoffset
andtz
are specified,tz
has the preference and thetzoffset
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 ...
- units (
-
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 adatetime
object; otherwise,false
Rtype: boolean
- value (
-
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: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 theinput_string
format. Possible values: ‘iso8601’, ‘rfc3339’, orstrptime
-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 ...
- input_string (
-
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 aninterval
object; otherwise,false
Rtype: boolean
Examples:
If a numeric value is passed to
is_interval()
, it returnsfalse
:tarantool> datetime = require('datetime') --- ... tarantool> datetime.interval.is_interval(123) --- - false ...
If an interval object is passed to
is_interval()
, it returnstrue
:tarantool> datetime.interval.is_interval(datetime.interval.new()) --- - true ...
- value (
-
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, theinterval
object with the default value0 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 ...
- input (
-
TZ
¶ Since: 2.11.0
A Lua table that maps timezone names (like
Europe/Moscow
) and timezone abbreviations (likeMSK
) 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
– yearsmonth
– monthsweek
– weeksday
– dayshour
– hoursmin
– minutessec
– secondsnsec
– 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, thetzoffset
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 fortzoffset
. So there might be some loss of precision if you try to operate with such ancient timestamps.