[Tarantool-patches] [PATCH v5 2/8] lua: built-in module datetime
Safin Timur
tsafin at tarantool.org
Wed Aug 18 02:30:57 MSK 2021
On 17.08.2021 15:15, Serge Petrenko wrote:
>
>
>> - check calculated attributes to date object, e.g.:
>> - timestamp, seconds, microseconds, minute, or hours
>> - to_utc(), and to_tz() allow to switch timezone of a
>> datetime object. It's not changing much - only timezone
>> but that impacts textual representation of a date.
>>
>> Part of #5941
>
> Please, add a docbot request to the commit message.
> Here it should say that you introduce lua datetime module
> and describe shortly what the module does.
I'm planning to cheat here - to not put detailed description to docbot
request part here, but rather to refer to the externally available
documentation I've written in
https://github.com/tarantool/tarantool/discussions/6244#discussioncomment-1043988
Like:
@TarantoolBot document
Title: Introduced new built-in `datetime` module
`datetime` module has been introduced, which allows to parse ISO-8601
literals representing timestamps of various formats, and then manipulate
with date objects.
Please refer to https://github.com/tarantool/tarantool/discussions/6244
for more detailed description of module API.
>
>> ---
>> cmake/BuildCDT.cmake | 2 +
>> extra/exports | 26 +
>> src/CMakeLists.txt | 2 +
>> src/lib/core/CMakeLists.txt | 1 +
>> src/lib/core/datetime.c | 96 ++++
>> src/lib/core/datetime.h | 95 ++++
>> src/lua/datetime.lua | 500 ++++++++++++++++++
>> src/lua/init.c | 4 +-
>> src/lua/utils.c | 27 +
>> src/lua/utils.h | 12 +
>> test/app-tap/datetime.test.lua | 206 ++++++++
>> .../gh-5632-6050-6259-gc-buf-reuse.test.lua | 74 ++-
>> 12 files changed, 1043 insertions(+), 2 deletions(-)
>> create mode 100644 src/lib/core/datetime.c
>> create mode 100644 src/lib/core/datetime.h
>> create mode 100644 src/lua/datetime.lua
>> create mode 100755 test/app-tap/datetime.test.lua
>>
>> diff --git a/cmake/BuildCDT.cmake b/cmake/BuildCDT.cmake
>> index 343fb1b99..80b26c64a 100644
>> --- a/cmake/BuildCDT.cmake
>> +++ b/cmake/BuildCDT.cmake
>> @@ -5,4 +5,6 @@ macro(libccdt_build)
>> file(MAKE_DIRECTORY
>> ${CMAKE_CURRENT_BINARY_DIR}/third_party/c-dt/build/)
>> add_subdirectory(${PROJECT_SOURCE_DIR}/third_party/c-dt
>>
>> ${CMAKE_CURRENT_BINARY_DIR}/third_party/c-dt/build/)
>> + set_target_properties(cdt PROPERTIES COMPILE_FLAGS
>> "-DDT_NAMESPACE=tnt_")
>> + add_definitions("-DDT_NAMESPACE=tnt_")
>> endmacro()
>
>
> This change belongs to the previous commit, doesn't it?
I considered that, but decided that for better observability purposes I
want to keep this rename of symbols via `tnt_` prefix closer to the code
where we exports those functions (please see `tnt_dt_dow` and others
below in the /extra/exports).
[But taking into account that we gonna squash these commits I don't care
that much now]
>
>
>> diff --git a/extra/exports b/extra/exports
>> index 9eaba1282..80eb92abd 100644
>> --- a/extra/exports
>> +++ b/extra/exports
>> @@ -148,8 +148,34 @@ csv_feed
>> csv_iterator_create
>> csv_next
>> csv_setopt
>> +datetime_asctime
>> +datetime_ctime
>> +datetime_now
>> +datetime_strftime
>> +decimal_unpack
>> decimal_from_string
>> decimal_unpack
These guys renamed here
|
V
>> +tnt_dt_dow
>> +tnt_dt_from_rdn
>> +tnt_dt_from_struct_tm
>> +tnt_dt_from_yd
>> +tnt_dt_from_ymd
>> +tnt_dt_from_yqd
>> +tnt_dt_from_ywd
>> +tnt_dt_parse_iso_date
>> +tnt_dt_parse_iso_time_basic
>> +tnt_dt_parse_iso_time_extended
>> +tnt_dt_parse_iso_time
>> +tnt_dt_parse_iso_zone_basic
>> +tnt_dt_parse_iso_zone_extended
>> +tnt_dt_parse_iso_zone_lenient
>> +tnt_dt_parse_iso_zone
>> +tnt_dt_rdn
>> +tnt_dt_to_struct_tm
>> +tnt_dt_to_yd
>> +tnt_dt_to_ymd
>> +tnt_dt_to_yqd
>> +tnt_dt_to_ywd
>> error_ref
>> error_set_prev
>> error_unref
>> diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
>> index 97b0cb326..4473ff1da 100644
>> --- a/src/CMakeLists.txt
>> +++ b/src/CMakeLists.txt
>> @@ -51,6 +51,8 @@ lua_source(lua_sources ../third_party/luafun/fun.lua)
>> lua_source(lua_sources lua/httpc.lua)
>> lua_source(lua_sources lua/iconv.lua)
>> lua_source(lua_sources lua/swim.lua)
>> +lua_source(lua_sources lua/datetime.lua)
>> +
>> # LuaJIT jit.* library
>> lua_source(lua_sources ${LUAJIT_SOURCE_ROOT}/src/jit/bc.lua)
>> lua_source(lua_sources ${LUAJIT_SOURCE_ROOT}/src/jit/bcsave.lua)
>> diff --git a/src/lib/core/CMakeLists.txt b/src/lib/core/CMakeLists.txt
>> index 2cd4d0b4f..8bc776b82 100644
>> --- a/src/lib/core/CMakeLists.txt
>> +++ b/src/lib/core/CMakeLists.txt
>> @@ -30,6 +30,7 @@ set(core_sources
>> decimal.c
>> mp_decimal.c
>> cord_buf.c
>> + datetime.c
>> )
>> if (TARGET_OS_NETBSD)
>> diff --git a/src/lib/core/datetime.c b/src/lib/core/datetime.c
>> new file mode 100644
>> index 000000000..c48295a6f
>> --- /dev/null
>> +++ b/src/lib/core/datetime.c
>> @@ -0,0 +1,96 @@
>> +/*
>> + * Copyright 2021, Tarantool AUTHORS, please see AUTHORS file.
>> + *
>> + * Redistribution and use in source and binary forms, with or
>> + * without modification, are permitted provided that the following
>> + * conditions are met:
>> + *
>> + * 1. Redistributions of source code must retain the above
>> + * copyright notice, this list of conditions and the
>> + * following disclaimer.
>> + *
>> + * 2. Redistributions in binary form must reproduce the above
>> + * copyright notice, this list of conditions and the following
>> + * disclaimer in the documentation and/or other materials
>> + * provided with the distribution.
>> + *
>> + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
>> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
>> + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
>> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
>> + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
>> + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
>> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
>> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
>> + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
>> + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
>> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
>> + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>> + * SUCH DAMAGE.
>> + */
>> +
>
> As far as I know, we switched to the following license format recently:
>
> /*
> * SPDX-License-Identifier: BSD-2-Clause
> *
> * Copyright 2010-2021, Tarantool AUTHORS, please see AUTHORS file.
> */
Much shorter - I like it. Updated.
>
> See, for example:
>
> ./src/box/module_cache.c: * SPDX-License-Identifier: BSD-2-Clause
> ./src/box/lua/lib.c: * SPDX-License-Identifier: BSD-2-Clause
> ./src/box/lua/lib.h: * SPDX-License-Identifier: BSD-2-Clause
> ./src/box/module_cache.h: * SPDX-License-Identifier: BSD-2-Clause
> ./src/lib/core/cord_buf.c: * SPDX-License-Identifier: BSD-2-Clause
> ./src/lib/core/crash.c: * SPDX-License-Identifier: BSD-2-Clause
> ./src/lib/core/cord_buf.h: * SPDX-License-Identifier: BSD-2-Clause
> ./src/lib/core/crash.h: * SPDX-License-Identifier: BSD-2-Clause
>
>
> <stripped>
>
>
>> diff --git a/src/lib/core/datetime.h b/src/lib/core/datetime.h
>> new file mode 100644
>> index 000000000..1a8d7e34f
>> --- /dev/null
>> +++ b/src/lib/core/datetime.h
>> @@ -0,0 +1,95 @@
>> +#pragma once
>> +/*
>> + * Copyright 2021, Tarantool AUTHORS, please see AUTHORS file.
>> + *
>> + * Redistribution and use in source and binary forms, with or
>> + * without modification, are permitted provided that the following
>> + * conditions are met:
>> + *
>> + * 1. Redistributions of source code must retain the above
>> + * copyright notice, this list of conditions and the
>> + * following disclaimer.
>> + *
>> + * 2. Redistributions in binary form must reproduce the above
>> + * copyright notice, this list of conditions and the following
>> + * disclaimer in the documentation and/or other materials
>> + * provided with the distribution.
>> + *
>> + * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
>> + * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
>> + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
>> + * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
>> + * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
>> + * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
>> + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
>> + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
>> + * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
>> + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
>> + * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
>> + * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
>> + * SUCH DAMAGE.
>> + */
>> +
>
> Same about the license.
Updated
>
> And I'd move the "#pragma once" below the license comment.
> Otherwise it's easily lost. Up to you.
On one side I agreed that it might left unrecognizable for untrained
eye. But on other side - the sooner compiler/preprocessor will see, the
better :)
[And there is already well established convention to put it at the first
line.]
So I've left it on the 1st line.
>
>> +#include <stdint.h>
>> +#include <stdbool.h>
>> +#include <stdio.h>
>
> AFAICS you don't need stdio included here.
Indeed!
>
>> +#include "c-dt/dt.h"
>> +
>> +#if defined(__cplusplus)
>> +extern "C"
>> +{
>> +#endif /* defined(__cplusplus) */
>> +
>> +#ifndef SECS_PER_DAY
>> +#define SECS_PER_DAY 86400
>> +#define DT_EPOCH_1970_OFFSET 719163
>
> Please, add a short comment on what this is.
> I had to spend some time googling to understand.
>
> So, please mention that this is measured in days from 01-01-0001.
I've written some explanation about these magic numbers. Now it's
verboser a bit:
--------------------------------------------------------
/**
* We count dates since so called "Rata Die" date
* January 1, 0001, Monday (as Day 1).
* But datetime structure keeps seconds since
* Unix "Epoch" date:
* Unix, January 1, 1970, Thursday
*
* The difference between Epoch (1970-01-01)
* and Rata Die (0001-01-01) is 719163 days.
*/
#ifndef SECS_PER_DAY
#define SECS_PER_DAY 86400
#define DT_EPOCH_1970_OFFSET 719163
#endif
--------------------------------------------------------
also, for the MP-related patch, I've added this comment, and defines
(might be used in asserts):
--------------------------------------------------------
/**
* c-dt library uses int as type for dt value, which
* represents the number of days since Rata Die date.
* This implies limits to the number of seconds we
* could safely store in our structures and then safely
* pass to c-dt functions.
*
* So supported ranges will be
* - for seconds [-185604722870400 .. 185480451417600]
* - for dates [-5879610-06-22T00:00Z .. 5879611-07-11T00:00Z]
*/
#define MAX_DT_DAY_VALUE (int64_t)INT_MAX
#define MIN_DT_DAY_VALUE (int64_t)INT_MIN
#define SECS_EPOCH_1970_OFFSET \
((int64_t)DT_EPOCH_1970_OFFSET * SECS_PER_DAY)
#define MAX_EPOCH_SECS_VALUE \
(MAX_DT_DAY_VALUE * SECS_PER_DAY - SECS_EPOCH_1970_OFFSET)
#define MIN_EPOCH_SECS_VALUE \
(MIN_DT_DAY_VALUE * SECS_PER_DAY - SECS_EPOCH_1970_OFFSET)
--------------------------------------------------------
>
>> +#endif
>> +
>> +/**
>> + * Full datetime structure representing moments
>> + * since Unix Epoch (1970-01-01).
>> + * Time is kept normalized to UTC, time-zone offset
>> + * is informative only.
>> + */
>> +struct datetime {
>> + /** seconds since epoch */
>> + double secs;
>> + /** nanoseconds if any */
>> + int32_t nsec;
>
>
> As discussed, let's make nsec a uint32_t, since
> nsec part is always positive.
Changed.
>
>
>> + /** offset in minutes from UTC */
>> + int32_t offset;
>> +};
>> +
>> +/**
>> + * Date/time interval structure
>> + */
>> +struct datetime_interval {
>> + /** relative seconds delta */
>> + double secs;
>> + /** nanoseconds delta */
>> + int32_t nsec;
>> +};
>> +
>
>
> Please start comments with a capital letter and end them with a dot.
Done.
>
>
>> +/**
>> + * Convert datetime to string using default asctime format
>> + * "Sun Sep 16 01:03:52 1973\n\0"
>> + * Wrapper around reenterable asctime_r() version of POSIX function
>> + * @param date source datetime value
>> + * @sa datetime_ctime
>> + */
>> +char *
>> +datetime_asctime(const struct datetime *date, char *buf);
>> +
>> +char *
>> +datetime_ctime(const struct datetime *date, char *buf);
>> +
>> +size_t
>> +datetime_strftime(const struct datetime *date, const char *fmt, char
>> *buf,
>> + uint32_t len);
>> +
>> +void
>> +datetime_now(struct datetime * now);
>> +
>> +#if defined(__cplusplus)
>> +} /* extern "C" */
>> +#endif /* defined(__cplusplus) */
>> diff --git a/src/lua/datetime.lua b/src/lua/datetime.lua
>> new file mode 100644
>> index 000000000..ce579828f
>> --- /dev/null
>> +++ b/src/lua/datetime.lua
>> @@ -0,0 +1,500 @@
>> +local ffi = require('ffi')
>> +
>> +ffi.cdef [[
>> +
>> + /*
>> + `c-dt` library functions handles properly both positive and
>> negative `dt`
>> + values, where `dt` is a number of dates since Rata Die date
>> (0001-01-01).
>> +
>> + For better compactness of our typical data in MessagePack stream
>> we shift
>> + root of our time to the Unix Epoch date (1970-01-01), thus our 0 is
>> + actually dt = 719163.
>> +
>> + So here is a simple formula how convert our epoch-based seconds
>> to dt values
>> + dt = (secs / 86400) + 719163
>> + Where 719163 is an offset of Unix Epoch (1970-01-01) since Rata Die
>> + (0001-01-01) in dates.
>> +
>> + */
>
>
> I'd move the comments outside the ffi.cdef block. This way they'd get
> proper highlighting, and it would be harder to mess something up
> by accidentally deleting the "*/"
Extracted.
>
>
>> + typedef int dt_t;
>> +
>> + // dt_core.h
>> + dt_t tnt_dt_from_rdn (int n);
>> + dt_t tnt_dt_from_ymd (int y, int m, int d);
>> +
>> + int tnt_dt_rdn (dt_t dt);
>> +
>> + // dt_parse_iso.h
>> + size_t tnt_dt_parse_iso_date (const char *str, size_t
>> len, dt_t *dt);
>> + size_t tnt_dt_parse_iso_time (const char *str, size_t
>> len, int *sod, int *nsec);
>> + size_t tnt_dt_parse_iso_zone_lenient (const char *str, size_t
>> len, int *offset);
>> +
>> + // datetime.c
>
>
> Also you may split the definitions into multiple ffi.cdef[[]] blocks
> if you want to add some per-definition comments.
>
Have split it into several. Like that
------------------------------------
diff --git a/src/lua/datetime.lua b/src/lua/datetime.lua
index ce579828f..7601421b1 100644
--- a/src/lua/datetime.lua
+++ b/src/lua/datetime.lua
@@ -1,8 +1,6 @@
local ffi = require('ffi')
-ffi.cdef [[
-
- /*
+--[[
`c-dt` library functions handles properly both positive and
negative `dt`
values, where `dt` is a number of dates since Rata Die date
(0001-01-01).
@@ -14,22 +12,27 @@ ffi.cdef [[
dt = (secs / 86400) + 719163
Where 719163 is an offset of Unix Epoch (1970-01-01) since Rata Die
(0001-01-01) in dates.
+]]
- */
+-- dt_core.h definitions
+ffi.cdef [[
typedef int dt_t;
- // dt_core.h
dt_t tnt_dt_from_rdn (int n);
dt_t tnt_dt_from_ymd (int y, int m, int d);
int tnt_dt_rdn (dt_t dt);
+]]
- // dt_parse_iso.h
+-- dt_parse_iso.h definitions
+ffi.cdef [[
size_t tnt_dt_parse_iso_date (const char *str, size_t
len, dt_t *dt);
size_t tnt_dt_parse_iso_time (const char *str, size_t
len, int *sod, int *nsec);
size_t tnt_dt_parse_iso_zone_lenient (const char *str, size_t
len, int *offset);
+]]
- // datetime.c
+-- Tarantool functions - datetime.c
+ffi.cdef [[
int
datetime_to_string(const struct datetime * date, char *buf,
uint32_t len);
@@ -45,7 +48,6 @@ ffi.cdef [[
void
datetime_now(struct datetime * now);
-
]]
local builtin = ffi.C
------------------------------------
>
>> + int
>> + datetime_to_string(const struct datetime * date, char *buf,
>> uint32_t len);
>> +
>> + char *
>> + datetime_asctime(const struct datetime *date, char *buf);
>> +
>> + char *
>> + datetime_ctime(const struct datetime *date, char *buf);
>> +
>> + size_t
>> + datetime_strftime(const struct datetime *date, const char *fmt,
>> char *buf,
>> + uint32_t len);
>> +
>> + void
>> + datetime_now(struct datetime * now);
>> +
>> +]]
>
>
> <stripped>
>
>
>> diff --git a/test/app-tap/datetime.test.lua
>> b/test/app-tap/datetime.test.lua
>> new file mode 100755
>> index 000000000..464d4bd49
>> --- /dev/null
>> +++ b/test/app-tap/datetime.test.lua
>> @@ -0,0 +1,206 @@
>> +#!/usr/bin/env tarantool
>> +
>> +local tap = require('tap')
>> +local test = tap.test("errno")
>> +local date = require('datetime')
>> +local ffi = require('ffi')
>> +
>> +
>> +test:plan(6)
>> +
>> +test:test("Simple tests for parser", function(test)
>> + test:plan(2)
>> + test:ok(date("1970-01-01T01:00:00Z") ==
>> + date {year=1970, month=1, day=1, hour=1, minute=0,
>> second=0})
>> + test:ok(date("1970-01-01T02:00:00+02:00") ==
>> + date {year=1970, month=1, day=1, hour=2, minute=0,
>> second=0, tz=120})
>> +end)
>> +
>> +test:test("Multiple tests for parser (with nanoseconds)", function(test)
>> + test:plan(168)
>> + -- borrowed from p5-time-moments/t/180_from_string.t
>> + local tests =
>> + {
>> + { '1970-01-01T00:00:00Z', 0,
>> 0, 0 },
>> + { '1970-01-01T02:00:00+02:00', 0,
>> 0, 120 },
>> + { '1970-01-01T01:30:00+01:30', 0,
>> 0, 90 },
>> + { '1970-01-01T01:00:00+01:00', 0,
>> 0, 60 },
>> + { '1970-01-01T00:01:00+00:01', 0,
>> 0, 1 },
>> + { '1970-01-01T00:00:00+00:00', 0,
>> 0, 0 },
>> + { '1969-12-31T23:59:00-00:01', 0,
>> 0, -1 },
>> + { '1969-12-31T23:00:00-01:00', 0,
>> 0, -60 },
>> + { '1969-12-31T22:30:00-01:30', 0,
>> 0, -90 },
>> + { '1969-12-31T22:00:00-02:00', 0,
>> 0, -120 },
>> + { '1970-01-01T00:00:00.123456789Z', 0,
>> 123456789, 0 },
>> + { '1970-01-01T00:00:00.12345678Z', 0,
>> 123456780, 0 },
>> + { '1970-01-01T00:00:00.1234567Z', 0,
>> 123456700, 0 },
>> + { '1970-01-01T00:00:00.123456Z', 0,
>> 123456000, 0 },
>> + { '1970-01-01T00:00:00.12345Z', 0,
>> 123450000, 0 },
>> + { '1970-01-01T00:00:00.1234Z', 0,
>> 123400000, 0 },
>> + { '1970-01-01T00:00:00.123Z', 0,
>> 123000000, 0 },
>> + { '1970-01-01T00:00:00.12Z', 0,
>> 120000000, 0 },
>> + { '1970-01-01T00:00:00.1Z', 0,
>> 100000000, 0 },
>> + { '1970-01-01T00:00:00.01Z', 0,
>> 10000000, 0 },
>> + { '1970-01-01T00:00:00.001Z', 0,
>> 1000000, 0 },
>> + { '1970-01-01T00:00:00.0001Z', 0,
>> 100000, 0 },
>> + { '1970-01-01T00:00:00.00001Z', 0,
>> 10000, 0 },
>> + { '1970-01-01T00:00:00.000001Z', 0,
>> 1000, 0 },
>> + { '1970-01-01T00:00:00.0000001Z', 0,
>> 100, 0 },
>> + { '1970-01-01T00:00:00.00000001Z', 0,
>> 10, 0 },
>> + { '1970-01-01T00:00:00.000000001Z', 0,
>> 1, 0 },
>> + { '1970-01-01T00:00:00.000000009Z', 0,
>> 9, 0 },
>> + { '1970-01-01T00:00:00.00000009Z', 0,
>> 90, 0 },
>> + { '1970-01-01T00:00:00.0000009Z', 0,
>> 900, 0 },
>> + { '1970-01-01T00:00:00.000009Z', 0,
>> 9000, 0 },
>> + { '1970-01-01T00:00:00.00009Z', 0,
>> 90000, 0 },
>> + { '1970-01-01T00:00:00.0009Z', 0,
>> 900000, 0 },
>> + { '1970-01-01T00:00:00.009Z', 0,
>> 9000000, 0 },
>> + { '1970-01-01T00:00:00.09Z', 0,
>> 90000000, 0 },
>> + { '1970-01-01T00:00:00.9Z', 0,
>> 900000000, 0 },
>> + { '1970-01-01T00:00:00.99Z', 0,
>> 990000000, 0 },
>> + { '1970-01-01T00:00:00.999Z', 0,
>> 999000000, 0 },
>> + { '1970-01-01T00:00:00.9999Z', 0,
>> 999900000, 0 },
>> + { '1970-01-01T00:00:00.99999Z', 0,
>> 999990000, 0 },
>> + { '1970-01-01T00:00:00.999999Z', 0,
>> 999999000, 0 },
>> + { '1970-01-01T00:00:00.9999999Z', 0,
>> 999999900, 0 },
>> + { '1970-01-01T00:00:00.99999999Z', 0,
>> 999999990, 0 },
>> + { '1970-01-01T00:00:00.999999999Z', 0,
>> 999999999, 0 },
>
> Красивое :)
:)
>
>> + { '1970-01-01T00:00:00.0Z', 0,
>> 0, 0 },
>> + { '1970-01-01T00:00:00.00Z', 0,
>> 0, 0 },
>> + { '1970-01-01T00:00:00.000Z', 0,
>> 0, 0 },
>> + { '1970-01-01T00:00:00.0000Z', 0,
>> 0, 0 },
>> + { '1970-01-01T00:00:00.00000Z', 0,
>> 0, 0 },
>> + { '1970-01-01T00:00:00.000000Z', 0,
>> 0, 0 },
>> + { '1970-01-01T00:00:00.0000000Z', 0,
>> 0, 0 },
>> + { '1970-01-01T00:00:00.00000000Z', 0,
>> 0, 0 },
>> + { '1970-01-01T00:00:00.000000000Z', 0,
>> 0, 0 },
>> + { '1973-11-29T21:33:09Z', 123456789,
>> 0, 0 },
>> + { '2013-10-28T17:51:56Z', 1382982716,
>> 0, 0 },
>> + { '9999-12-31T23:59:59Z', 253402300799,
>> 0, 0 },
>> + }
>> + for _, value in ipairs(tests) do
>> + local str, epoch, nsec, offset
>> + str, epoch, nsec, offset = unpack(value)
>> + local dt = date(str)
>> + test:ok(dt.secs == epoch, ('%s: dt.secs == %d'):format(str,
>> epoch))
>> + test:ok(dt.nsec == nsec, ('%s: dt.nsec == %d'):format(str,
>> nsec))
>> + test:ok(dt.offset == offset, ('%s: dt.offset ==
>> %d'):format(str, offset))
>> + end
>> +end)
>> +
>> +ffi.cdef [[
>> + void tzset(void);
>> +]]
>> +
>>
>
>
> <stripped>
>
>
>
Here is (was) incremental patch. [Now it's slightly changed, with
MP-related defines, but you got the point]:
------------------------------------------------------------------
diff --git a/src/lib/core/datetime.c b/src/lib/core/datetime.c
index c48295a6f..719a4cd47 100644
--- a/src/lib/core/datetime.c
+++ b/src/lib/core/datetime.c
@@ -1,32 +1,7 @@
/*
- * Copyright 2021, Tarantool AUTHORS, please see AUTHORS file.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the
- * following disclaimer.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * Copyright 2021, Tarantool AUTHORS, please see AUTHORS file.
*/
#include <string.h>
diff --git a/src/lib/core/datetime.h b/src/lib/core/datetime.h
index 1a8d7e34f..88774110c 100644
--- a/src/lib/core/datetime.h
+++ b/src/lib/core/datetime.h
@@ -1,38 +1,12 @@
#pragma once
/*
- * Copyright 2021, Tarantool AUTHORS, please see AUTHORS file.
- *
- * Redistribution and use in source and binary forms, with or
- * without modification, are permitted provided that the following
- * conditions are met:
- *
- * 1. Redistributions of source code must retain the above
- * copyright notice, this list of conditions and the
- * following disclaimer.
+ * SPDX-License-Identifier: BSD-2-Clause
*
- * 2. Redistributions in binary form must reproduce the above
- * copyright notice, this list of conditions and the following
- * disclaimer in the documentation and/or other materials
- * provided with the distribution.
- *
- * THIS SOFTWARE IS PROVIDED BY <COPYRIGHT HOLDER> ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
- * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
- * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
- * <COPYRIGHT HOLDER> OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
- * INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
- * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
- * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
- * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF
- * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
+ * Copyright 2021, Tarantool AUTHORS, please see AUTHORS file.
*/
#include <stdint.h>
#include <stdbool.h>
-#include <stdio.h>
#include "c-dt/dt.h"
#if defined(__cplusplus)
@@ -40,23 +14,34 @@ extern "C"
{
#endif /* defined(__cplusplus) */
+/**
+ * We count dates since so called "Rata Die" date
+ * January 1, 0001, Monday (as Day 1).
+ * But datetime structure keeps seconds since
+ * Unix "Epoch" date:
+ * Unix, January 1, 1970, Thursday
+ *
+ * The difference between Epoch (1970-01-01)
+ * and Rata Die (0001-01-01) is 719163 days.
+ */
+
#ifndef SECS_PER_DAY
#define SECS_PER_DAY 86400
#define DT_EPOCH_1970_OFFSET 719163
#endif
/**
- * Full datetime structure representing moments
- * since Unix Epoch (1970-01-01).
- * Time is kept normalized to UTC, time-zone offset
+ * datetime structure keeps number of seconds since
+ * Unix Epoch.
+ * Time is normalized by UTC, so time-zone offset
* is informative only.
*/
struct datetime {
- /** seconds since epoch */
+ /** Seconds since Epoch. */
double secs;
- /** nanoseconds if any */
- int32_t nsec;
- /** offset in minutes from UTC */
+ /** Nanoseconds, if any. */
+ uint32_t nsec;
+ /** Offset in minutes from UTC. */
int32_t offset;
};
@@ -64,10 +49,10 @@ struct datetime {
* Date/time interval structure
*/
struct datetime_interval {
- /** relative seconds delta */
+ /** Relative seconds delta. */
double secs;
- /** nanoseconds delta */
- int32_t nsec;
+ /** Nanoseconds delta, if any. */
+ uint32_t nsec;
};
/**
------------------------------------------------------------------
Thanks,
Timur
More information about the Tarantool-patches
mailing list