From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: <tarantool-patches-bounces@dev.tarantool.org> Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id CD7D56EC40; Wed, 18 Aug 2021 11:56:19 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org CD7D56EC40 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1629276979; bh=IeM9q39pVzjWVYHSKMBBHe9m01ieEaFEsAYm+IVQfvc=; h=To:References:Date:In-Reply-To:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=CAbLW49bAY9U71Tq8cSVyxiem57nP2UiMdDB293S5OHqvo/Om/82nKgz5I7v31lEc k7oDcVRWOLcqV32je4MfAeZ1tTAdqxEGDS62hrvCXJK8Wjtdjk8D3O00BuAf4RVP7A xOY24K9DnsK7fHJqbooqxz37+N1y8k3Axs6kyuDc= Received: from smtp47.i.mail.ru (smtp47.i.mail.ru [94.100.177.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by dev.tarantool.org (Postfix) with ESMTPS id 5E3AB6EC40 for <tarantool-patches@dev.tarantool.org>; Wed, 18 Aug 2021 11:56:18 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 5E3AB6EC40 Received: by smtp47.i.mail.ru with esmtpa (envelope-from <sergepetrenko@tarantool.org>) id 1mGHMu-0005au-TU; Wed, 18 Aug 2021 11:56:17 +0300 To: Safin Timur <tsafin@tarantool.org> References: <cover.1629071531.git.tsafin@tarantool.org> <d038b68adf2f28f14cc6dc3c6256101b72114d41.1629071531.git.tsafin@tarantool.org> <56906a41-d62c-96b9-6152-d01989b74acb@tarantool.org> <85040d30-2a0c-9ba1-5df9-46429ac4a756@tarantool.org> Message-ID: <2aeef940-50f3-574b-4e15-8bf2159aa688@tarantool.org> Date: Wed, 18 Aug 2021 11:56:16 +0300 User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10.15; rv:78.0) Gecko/20100101 Thunderbird/78.13.0 MIME-Version: 1.0 In-Reply-To: <85040d30-2a0c-9ba1-5df9-46429ac4a756@tarantool.org> Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 8bit Content-Language: en-GB X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD92087353F0EC44DD9BCE6B93DE0C6C3914462CDB1732D383C182A05F5380850403D17E756105C089377CA17D98E23360593D944A4EEB929C3C59613EB20666835 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7F2393C4755A27B53EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F79006372E000E903B06FBD58638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D80618F9D5AFD3ECC098A03984DAB4E48A117882F4460429724CE54428C33FAD305F5C1EE8F4F765FCAA867293B0326636D2E47CDBA5A96583BD4B6F7A4D31EC0BC014FD901B82EE079FA2833FD35BB23D27C277FBC8AE2E8BAA867293B0326636D2E47CDBA5A96583BA9C0B312567BB2376E601842F6C81A19E625A9149C048EE7B96B19DC40933219935A1E27F592749D8FC6C240DEA7642DBF02ECDB25306B2B78CF848AE20165D0A6AB1C7CE11FEE3034D30FDF2F620DB9735652A29929C6CC4224003CC836476EA7A3FFF5B025636E2021AF6380DFAD1A18204E546F3947CB11811A4A51E3B096D1867E19FE1407959CC434672EE6371089D37D7C0E48F6C8AA50765F790063788B3B24285A3CD0EEFF80C71ABB335746BA297DBC24807EABDAD6C7F3747799A X-B7AD71C0: AC4F5C86D027EB782CDD5689AFBDA7A213B5FB47DCBC3458834459D11680B505832C045202435C8BBB1F3F936A2C68FE X-C1DE0DAB: 0D63561A33F958A59DFC81C9FBB9A2FD9EDC6597F75E9277C2E13A53BFF30A43D59269BC5F550898D99A6476B3ADF6B47008B74DF8BB9EF7333BD3B22AA88B938A852937E12ACA757E10A58996CBD514410CA545F18667F91A7EA1CDA0B5A7A0 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D34C02783DDD5A45DEFEAAE3A1C7C7771E654E400F2E994708B308BBCE716B5D92CA2B513FD757523711D7E09C32AA3244CC862B043A2B3E359944F516D1F947714408A6A02710B730483B48618A63566E0 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojuRQ/H5n28trr8Tz2YYseLA== X-Mailru-Sender: 583F1D7ACE8F49BD31DE23046B3A846013DB5FD452412CFF05D564664438AD0F277E5B8677B2C9606BB2E709EA627F343C7DDD459B58856F0E45BC603594F5A135B915D4279FF0579437F6177E88F7363CDA0F3B3F5B9367 X-Mras: Ok Subject: Re: [Tarantool-patches] [PATCH v5 2/8] lua: built-in module datetime X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches <tarantool-patches.dev.tarantool.org> List-Unsubscribe: <https://lists.tarantool.org/mailman/options/tarantool-patches>, <mailto:tarantool-patches-request@dev.tarantool.org?subject=unsubscribe> List-Archive: <https://lists.tarantool.org/pipermail/tarantool-patches/> List-Post: <mailto:tarantool-patches@dev.tarantool.org> List-Help: <mailto:tarantool-patches-request@dev.tarantool.org?subject=help> List-Subscribe: <https://lists.tarantool.org/mailman/listinfo/tarantool-patches>, <mailto:tarantool-patches-request@dev.tarantool.org?subject=subscribe> From: Serge Petrenko via Tarantool-patches <tarantool-patches@dev.tarantool.org> Reply-To: Serge Petrenko <sergepetrenko@tarantool.org> Cc: tarantool-patches@dev.tarantool.org, v.shpilevoy@tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" <tarantool-patches-bounces@dev.tarantool.org> 18.08.2021 02:30, Safin Timur пишет: > 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. That's fine, I guess. > >> >>> --- >>> 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 Thanks for the changes! Looks good so far. I'll take a look at the whole series again once you push the updates to Vladimir's comments -- Serge Petrenko