From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from [87.239.111.99] (localhost [127.0.0.1]) by dev.tarantool.org (Postfix) with ESMTP id 01B6C741EE; Fri, 6 Aug 2021 03:30:09 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 01B6C741EE DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1628209809; bh=pDyaFRNvD2+WBFABG5TBPCVxxopjLbdP2epVPW3UvMQ=; 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=EEqiKaLfZD7VjxDUpcasSlOk6ttfvSB/3mswgAWXy261CqBpwKwi6jv/QSjeQgV+s 7SIKMcPoEDLfm8WgTcE87ChRp1UDnFPtYSGIYAkS09RXehnggVRAjgVf565rKDU038 B1zm5Kr3tKmC7euOnWuKmU5YucxIa9+BItAbLT4o= Received: from smtp32.i.mail.ru (smtp32.i.mail.ru [94.100.177.92]) (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 DB3AA741EE for ; Fri, 6 Aug 2021 03:30:06 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org DB3AA741EE Received: by smtp32.i.mail.ru with esmtpa (envelope-from ) id 1mBnkT-0003G8-Cy; Fri, 06 Aug 2021 03:30:05 +0300 To: v.shpilevoy@tarantool.org, olegrok@tarantool.org References: <5817f15e9db569675ce595cfd63a03bab1875c3c.1628025689.git.tsafin@tarantool.org> Message-ID: Date: Fri, 6 Aug 2021 03:30:05 +0300 User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:78.0) Gecko/20100101 Thunderbird/78.12.0 MIME-Version: 1.0 In-Reply-To: <5817f15e9db569675ce595cfd63a03bab1875c3c.1628025689.git.tsafin@tarantool.org> Content-Type: text/plain; charset=utf-8; format=flowed Content-Language: en-US Content-Transfer-Encoding: 7bit X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD92087353F0EC44DD9736CF3E71F18CE0C3E1D5927724F4AAA182A05F538085040AB8E16F7CEC87F79D827CBF8D102B8728A4CEDED84AE8E44C6FAD0D80053C2BB X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE7A3DED2DACB82E709C2099A533E45F2D0395957E7521B51C2CFCAF695D4D8E9FCEA1F7E6F0F101C6778DA827A17800CE7ACA11F7F2395C8CCEA1F7E6F0F101C6723150C8DA25C47586E58E00D9D99D84E1BDDB23E98D2D38BBCA57AF85F7723F2BBC09DBCF29D9BC669AAA65F6BB01F38CC7F00164DA146DAFE8445B8C89999728AA50765F7900637F6B57BC7E64490618DEB871D839B7333395957E7521B51C2DFABB839C843B9C08941B15DA834481F8AA50765F7900637F6B57BC7E6449061A352F6E88A58FB86F5D81C698A659EA73AA81AA40904B5D9A18204E546F3947C8BCE4D8A51BE8AA5AD7EC71F1DB884274AD6D5ED66289B52698AB9A7B718F8C46E0066C2D8992A16725E5C173C3A84C3AA9263D48448ECAFBA3038C0950A5D36B5C8C57E37DE458B0BC6067A898B09E46D1867E19FE14079C09775C1D3CA48CF3D321E7403792E342EB15956EA79C166A417C69337E82CC275ECD9A6C639B01B78DA827A17800CE732FCE54C4D9A645443847C11F186F3C59DAA53EE0834AAEE X-B7AD71C0: AC4F5C86D027EB782CDD5689AFBDA7A213B5FB47DCBC3458F0AFF96BAACF4158235E5A14AD4A4A4625E192CAD1D9E79D94463893BF8742D0AC2ACC32F74E2838 X-C1DE0DAB: 0D63561A33F958A54639166F0315FAE9B66FF68AEAAE1A8A49A3CF3470BD9890D59269BC5F550898D99A6476B3ADF6B47008B74DF8BB9EF7333BD3B22AA88B938A852937E12ACA7501A9DF589746230F410CA545F18667F91A7EA1CDA0B5A7A0 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D3442AF01057B6BF997132B8265D08B2D409D7F9079112C725B860D5A3F6395D72133CA930F5D590A5C1D7E09C32AA3244C659869DCB6AC933AB2027B914A78C19CD08D48398F32B4A683B48618A63566E0 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojFhlvmGwdUwT8Y4RG9o8JSg== X-Mailru-Sender: B5B6A6EBBD94DAD81091F6801AA03C016EBDA8A403CDE9A7A70BE323852DABCC9F1B0DBDF38183685C2808D6142752370A8ED71B308007E3DC85537438B7E1A423D748DE48713E689437F6177E88F7363CDA0F3B3F5B9367 X-Mras: Ok Subject: Re: [Tarantool-patches] [PATCH v3 2/2] lua, datetime: introduce ctime, strftime wrappers X-BeenThere: tarantool-patches@dev.tarantool.org X-Mailman-Version: 2.1.34 Precedence: list List-Id: Tarantool development patches List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , From: Safin Timur via Tarantool-patches Reply-To: Safin Timur Cc: tarantool-patches@dev.tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" This change is now part of patch 2/9 lua:built-in module datetime, and there is no platform specific Lua code in the module. Timur On 04.08.2021 0:23, Timur Safin wrote: > To make Lua code less platfrom dependent we move > all platform specifics to the C level. Specifically > we want to avoid dependence on `struct tm {}` layout > and GLIBC `strftime` behaviour. > As a bonus we have that after moving of time dependent > code to C we make Lua code significantly simpler and thus > may get rid of all implementation specific details > with numerous typedefs and function declarations. > > Part of #5941 > --- > src/exports.h | 4 ++ > src/lib/core/datetime.c | 63 +++++++++++++++++- > src/lib/core/datetime.h | 23 ++++++- > src/lua/datetime.lua | 139 +++++----------------------------------- > 4 files changed, 104 insertions(+), 125 deletions(-) > > diff --git a/src/exports.h b/src/exports.h > index 63efe0ec7..f4a6f98d7 100644 > --- a/src/exports.h > +++ b/src/exports.h > @@ -218,6 +218,10 @@ EXPORT(curl_version) > EXPORT(curl_version_info) > #endif /* EXPORT_LIBCURL_SYMBOLS */ > EXPORT(datetime_pack) > +EXPORT(datetime_asctime) > +EXPORT(datetime_ctime) > +EXPORT(datetime_now) > +EXPORT(datetime_strftime) > EXPORT(datetime_to_string) > EXPORT(datetime_unpack) > EXPORT(decimal_unpack) > diff --git a/src/lib/core/datetime.c b/src/lib/core/datetime.c > index 03facb123..a921cbd11 100755 > --- a/src/lib/core/datetime.c > +++ b/src/lib/core/datetime.c > @@ -30,6 +30,7 @@ > */ > > #include > +#include > > #include "trivia/util.h" > #include "datetime.h" > @@ -165,12 +166,35 @@ mp_encode_datetime(char *data, const struct datetime *date) > return datetime_pack(data, date); > } > > +static int > +local_dt(int64_t secs) > +{ > + return dt_from_rdn((int)(secs / SECS_PER_DAY) + DT_EPOCH_1970_OFFSET); > +} > + > +static struct tm * > +datetime_to_tm(const struct datetime *date) > +{ > + static struct tm tm; > + > + memset(&tm, 0, sizeof(tm)); > + int64_t secs = date->secs; > + dt_to_struct_tm(local_dt(secs), &tm); > + > + int seconds_of_day = date->secs % SECS_PER_DAY; > + tm.tm_hour = (seconds_of_day / 3600) % 24; > + tm.tm_min = (seconds_of_day / 60) % 60; > + tm.tm_sec = seconds_of_day % 60; > + > + return &tm; > +} > + > int datetime_to_string(const struct datetime *date, char *buf, uint32_t len) > { > char * src = buf; > int offset = date->offset; > int64_t secs = date->secs + offset * 60; > - dt_t dt = dt_from_rdn((secs / SECS_PER_DAY) + 719163); > + dt_t dt = local_dt(secs); > > int year, month, day, sec, ns, sign; > dt_to_ymd(dt, &year, &month, &day); > @@ -214,6 +238,43 @@ int datetime_to_string(const struct datetime *date, char *buf, uint32_t len) > return (buf - src); > } > > +void > +datetime_now(struct datetime * now) > +{ > + struct timeval tv; > + gettimeofday(&tv, NULL); > + now->secs = tv.tv_sec; > + now->nsec = tv.tv_usec * 1000; > + > + time_t now_seconds; > + time(&now_seconds); > + struct tm tm; > + localtime_r(&now_seconds, &tm); > + now->offset = tm.tm_gmtoff / 60; > +} > + > +char * > +datetime_asctime(const struct datetime *date) > +{ > + struct tm *p_tm = datetime_to_tm(date); > + return asctime(p_tm); > +} > + > +char * > +datetime_ctime(const struct datetime *date) > +{ > + time_t time = date->secs; > + return ctime(&time); > +} > + > +size_t > +datetime_strftime(const struct datetime *date, const char *fmt, char *buf, > + uint32_t len) > +{ > + struct tm *p_tm = datetime_to_tm(date); > + return strftime(buf, len, fmt, p_tm); > +} > + > int > mp_snprint_datetime(char *buf, int size, const char **data, uint32_t len) > { > diff --git a/src/lib/core/datetime.h b/src/lib/core/datetime.h > index 540bd68d9..012fb340d 100644 > --- a/src/lib/core/datetime.h > +++ b/src/lib/core/datetime.h > @@ -42,6 +42,7 @@ extern "C" > > #ifndef SECS_PER_DAY > #define SECS_PER_DAY 86400 > +#define DT_EPOCH_1970_OFFSET 719163 > #endif > > /** > @@ -102,7 +103,27 @@ mp_encode_datetime(char *data, const struct datetime *date); > * @param buf output character buffer > * @param len size ofoutput buffer > */ > -int datetime_to_string(const struct datetime *date, char *buf, uint32_t len); > +int > +datetime_to_string(const struct datetime *date, char *buf, uint32_t len); > + > +/** > + * Convert datetime to string using default asctime format > + * "Sun Sep 16 01:03:52 1973\n\0" > + * @param date source datetime value > + * @sa datetime_ctime > + */ > +char * > +datetime_asctime(const struct datetime *date); > + > +char * > +datetime_ctime(const struct datetime *date); > + > +size_t > +datetime_strftime(const struct datetime *date, const char *fmt, char *buf, > + uint32_t len); > + > +void > +datetime_now(struct datetime * now); > > int > mp_snprint_datetime(char *buf, int size, const char **data, uint32_t len); > diff --git a/src/lua/datetime.lua b/src/lua/datetime.lua > index 5cad4e02f..1549735bd 100644 > --- a/src/lua/datetime.lua > +++ b/src/lua/datetime.lua > @@ -82,90 +82,18 @@ ffi.cdef [[ > int > datetime_to_string(const struct datetime * date, char *buf, uint32_t len); > > + char * > + datetime_asctime(const struct datetime *date); > > - // > - typedef long __kernel_long_t; > - typedef unsigned long __kernel_ulong_t; > - // /usr/include/x86_64-linux-gnu/bits/types/time_t.h > - typedef long time_t; > + char * > + datetime_ctime(const struct datetime *date); > > + size_t > + datetime_strftime(const struct datetime *date, const char *fmt, char *buf, > + uint32_t len); > > - // > - typedef __kernel_long_t __kernel_time_t; > - typedef __kernel_long_t __kernel_suseconds_t; > - > - struct timespec { > - __kernel_time_t tv_sec; /* seconds */ > - long tv_nsec; /* nanoseconds */ > - }; > - > - struct timeval { > - __kernel_time_t tv_sec; /* seconds */ > - __kernel_suseconds_t tv_usec; /* microseconds */ > - }; > - > - struct timezone { > - int tz_minuteswest; /* minutes west of Greenwich */ > - int tz_dsttime; /* type of dst correction */ > - }; > - > - // /usr/include/x86_64-linux-gnu/sys/time.h > - typedef struct timezone * __timezone_ptr_t; > - > - /* Get the current time of day and timezone information, > - putting it into *TV and *TZ. If TZ is NULL, *TZ is not filled. > - Returns 0 on success, -1 on errors. > - > - NOTE: This form of timezone information is obsolete. > - Use the functions and variables declared in instead. */ > - int gettimeofday (struct timeval *__tv, struct timezone * __tz); > - > - // /usr/include/x86_64-linux-gnu/bits/types/struct_tm.h > - /* ISO C `broken-down time' structure. */ > - struct tm > - { > - int tm_sec; /* Seconds. [0-60] (1 leap second) */ > - int tm_min; /* Minutes. [0-59] */ > - int tm_hour; /* Hours. [0-23] */ > - int tm_mday; /* Day. [1-31] */ > - int tm_mon; /* Month. [0-11] */ > - int tm_year; /* Year - 1900. */ > - int tm_wday; /* Day of week. [0-6] */ > - int tm_yday; /* Days in year.[0-365] */ > - int tm_isdst; /* DST. [-1/0/1]*/ > - > - long int tm_gmtoff; /* Seconds east of UTC. */ > - const char *tm_zone;/* Timezone abbreviation. */ > - }; > - > - // > - /* Return the current time and put it in *TIMER if TIMER is not NULL. */ > - time_t time (time_t *__timer); > - > - /* Format TP into S according to FORMAT. > - Write no more than MAXSIZE characters and return the number > - of characters written, or 0 if it would exceed MAXSIZE. */ > - size_t strftime (char * __s, size_t __maxsize, const char * __format, > - const struct tm * __tp); > - > - /* Parse S according to FORMAT and store binary time information in TP. > - The return value is a pointer to the first unparsed character in S. */ > - char *strptime (const char * __s, const char * __fmt, struct tm *__tp); > - > - /* Return the `struct tm' representation of *TIMER in UTC, > - using *TP to store the result. */ > - struct tm *gmtime_r (const time_t * __timer, struct tm * __tp); > - > - /* Return the `struct tm' representation of *TIMER in local time, > - using *TP to store the result. */ > - struct tm *localtime_r (const time_t * __timer, struct tm * __tp); > - > - /* Return a string of the form "Day Mon dd hh:mm:ss yyyy\n" > - that is the representation of TP in this format. */ > - char *asctime (const struct tm *__tp); > - > - /* Equivalent to `asctime (localtime (timer))'. */ > - char *ctime (const time_t *__timer); > + void > + datetime_now(struct datetime * now); > > ]] > > @@ -921,62 +849,27 @@ local function datetime_from(o) > end > > local function local_now() > - local p_tv = ffi.new('struct timeval [1]') > - local rc = builtin.gettimeofday(p_tv, nil) > - assert(rc == 0) > - > - local secs = p_tv[0].tv_sec > - local nsec = p_tv[0].tv_usec * 1000 > - > - local p_time = ffi.new('time_t[1]') > - local p_tm = ffi.new('struct tm[1]') > - builtin.time(p_time) > - builtin.localtime_r(p_time, p_tm) > - local ofs = p_tm[0].tm_gmtoff / 60 -- convert seconds to minutes > - > - return datetime_new_raw(secs, nsec, ofs) > -end > - > -local function datetime_to_tm_ptr(o) > - assert(is_datetime(o)) > - local p_tm = ffi.new('struct tm[1]') > - -- dt_to_struct_tm() fills only date data > - builtin.dt_to_struct_tm(local_dt(o), p_tm) > - > - -- calculate the smaller data (hour, minute, > - -- seconds) using datetime seconds value > - local seconds_of_day = o.secs % 86400 > - local hour = (seconds_of_day / 3600) % 24 > - local minute = (seconds_of_day / 60) % 60 > - p_tm[0].tm_sec = seconds_of_day % 60 > - p_tm[0].tm_min = minute > - p_tm[0].tm_hour = hour > - > - p_tm[0].tm_gmtoff = o.offset * 60 > - > - return p_tm > + local d = datetime_new_raw(0, 0, 0) > + builtin.datetime_now(d) > + return d > end > > local function asctime(o) > check_date(o, "datetime:asctime()") > > - local p_tm = datetime_to_tm_ptr(o) > - return ffi.string(builtin.asctime(p_tm)) > + return ffi.string(builtin.datetime_asctime(o)) > end > > local function ctime(o) > check_date(o, "datetime:ctime()") > - local p_time = ffi.new('time_t[1]') > - p_time[0] = o.secs > - return ffi.string(builtin.ctime(p_time)) > + return ffi.string(builtin.datetime_ctime(o)) > end > > local function strftime(fmt, o) > check_date(o, "datetime.strftime()") > - local p_tm = datetime_to_tm_ptr(o) > - local sz = builtin.strftime(nil, 1024, fmt, p_tm) + 1 > + local sz = 128 > local buff = ffi.new('char[?]', sz) > - builtin.strftime(buff, sz, fmt, p_tm) > + builtin.datetime_strftime(o, fmt, buff, sz) > return ffi.string(buff) > end > >