From: Safin Timur via Tarantool-patches <tarantool-patches@dev.tarantool.org>
To: Vladimir Davydov <vdavydov@tarantool.org>,
Timur Safin via Tarantool-patches
<tarantool-patches@dev.tarantool.org>
Cc: v.shpilevoy@tarantool.org
Subject: Re: [Tarantool-patches] [PATCH v5 3/8] lua, datetime: display datetime
Date: Wed, 18 Aug 2021 17:10:50 +0300 [thread overview]
Message-ID: <b9f86b63-9a6d-c7a8-b365-0d30eaf4b4c7@tarantool.org> (raw)
In-Reply-To: <20210817170637.x3ilanywpmgbugj5@esperanza>
On 17.08.2021 20:06, Vladimir Davydov via Tarantool-patches wrote:
> On Mon, Aug 16, 2021 at 02:59:37AM +0300, Timur Safin via
> Tarantool-patches wrote:
>> * introduced output routine for converting datetime
>> to their default output format.
>>
>> * use this routine for tostring() in datetime.lua
>>
>> Part of #5941
>> ---
>> extra/exports | 1 +
>> src/lib/core/datetime.c | 71 ++++++++++++++++++
>> src/lib/core/datetime.h | 9 +++
>> src/lua/datetime.lua | 35 +++++++++
>> test/app-tap/datetime.test.lua | 131 ++++++++++++++++++---------------
>> test/unit/CMakeLists.txt | 2 +-
>> test/unit/datetime.c | 61 +++++++++++----
>> 7 files changed, 236 insertions(+), 74 deletions(-)
>>
>> diff --git a/extra/exports b/extra/exports
>> index 80eb92abd..2437e175c 100644
>> --- a/extra/exports
>> +++ b/extra/exports
>> @@ -152,6 +152,7 @@ datetime_asctime
>> datetime_ctime
>> datetime_now
>> datetime_strftime
>> +datetime_to_string
>> decimal_unpack
>> decimal_from_string
>> decimal_unpack
>> diff --git a/src/lib/core/datetime.c b/src/lib/core/datetime.c
>> index c48295a6f..c24a0df82 100644
>> --- a/src/lib/core/datetime.c
>> +++ b/src/lib/core/datetime.c
>> @@ -29,6 +29,8 @@
>> * SUCH DAMAGE.
>> */
>>
>> +#include <assert.h>
>> +#include <limits.h>
>> #include <string.h>
>> #include <time.h>
>>
>> @@ -94,3 +96,72 @@ datetime_strftime(const struct datetime *date, const
> char *fmt, char *buf,
>> struct tm *p_tm = datetime_to_tm(date);
>> return strftime(buf, len, fmt, p_tm);
>> }
>> +
>> +#define SECS_EPOCH_1970_OFFSET ((int64_t)DT_EPOCH_1970_OFFSET *
> SECS_PER_DAY)
>> +
>> +/* NB! buf may be NULL, and we should handle it gracefully, returning
>
> /**
> * ...
>
> (according to our coding style)
AFAIK external comments (in headers) should be doxygen, but internal
comments (in the implementation) may be not in doxygen format. That's
internal comment.
>
>> + * calculated length of output string
>> + */
>> +int
>> +datetime_to_string(const struct datetime *date, char *buf, uint32_t
> len)
>> +{
>> +#define ADVANCE(sz) \
>> + if (buf != NULL) { \
>> + buf += sz; \
>> + len -= sz; \
>> + } \
>> + ret += sz;
>
> Please use SNPRINT helper.
Yes, already has have it reimplemented after Serge Petrenko comment.
It's a little bit shorter now. Nice!
>
>> +
>> + int offset = date->offset;
>> + /* for negative offsets around Epoch date we could get
>> + * negative secs value, which should be attributed to
>> + * 1969-12-31, not 1970-01-01, thus we first shift
>> + * epoch to Rata Die then divide by seconds per day,
>> + * not in reverse
>> + */
>> + int64_t secs = (int64_t)date->secs + offset * 60 +
> SECS_EPOCH_1970_OFFSET;
>> + assert((secs / SECS_PER_DAY) <= INT_MAX);
>> + dt_t dt = dt_from_rdn(secs / SECS_PER_DAY);
>> +
>> + int year, month, day, sec, ns, sign;
>> + dt_to_ymd(dt, &year, &month, &day);
>> +
>> + int hour = (secs / 3600) % 24,
>> + minute = (secs / 60) % 60;
>
> Please define on a separate line:
>
> int hour = ...;
> int minute = ...;
Done.
>
>> + sec = secs % 60;
>
> sec, secs, oh
>
> Please use better names.
Renamed.
>
>> + ns = date->nsec;
>> +
>> + int ret = 0;
>> + uint32_t sz = snprintf(buf, len, "%04d-%02d-%02dT%02d:%02d",
>> + year, month, day, hour, minute);
>> + ADVANCE(sz);
>> + if (sec || ns) {
>> + sz = snprintf(buf, len, ":%02d", sec);
>> + ADVANCE(sz);
>> + if (ns) {
>> + if ((ns % 1000000) == 0)
>> + sz = snprintf(buf, len, ".%03d", ns /
> 1000000);
>> + else if ((ns % 1000) == 0)
>> + sz = snprintf(buf, len, ".%06d", ns /
> 1000);
>> + else
>> + sz = snprintf(buf, len, ".%09d", ns);
>> + ADVANCE(sz);
>> + }
>> + }
>> + if (offset == 0) {
>> + sz = snprintf(buf, len, "Z");
>> + ADVANCE(sz);
>> + }
>> + else {
>
> Bad formatting. Should be '} else {'.
Fixed.
>
>> + if (offset < 0)
>> + sign = '-', offset = -offset;
>
> Please don't abuse ','.
>
>> + else
>> + sign = '+';
>> +
>> + sz = snprintf(buf, len, "%c%02d:%02d", sign, offset / 60,
> offset % 60);
>> + ADVANCE(sz);
>> + }
>> + return ret;
>> +}
>> +#undef ADVANCE
>> +
>> diff --git a/src/lib/core/datetime.h b/src/lib/core/datetime.h
>> index 1a8d7e34f..964e76fcc 100644
>> --- a/src/lib/core/datetime.h
>> +++ b/src/lib/core/datetime.h
>> @@ -70,6 +70,15 @@ struct datetime_interval {
>> int32_t nsec;
>> };
>>
>> +/**
>> + * Convert datetime to string using default format
>> + * @param date source datetime value
>> + * @param buf output character buffer
>> + * @param len size ofoutput buffer
>> + */
>> +int
>> +datetime_to_string(const struct datetime *date, char *buf, uint32_t
> len);
>> +
>
> This should be an snprint-like function: buf and len should go first.
> This would allow us to use it in conjunction with SNPRINT.
Will reorder.
[BTW, if we keep argument at the same order then for x64 ABI, with
fastcall and upto 6 arguments passed via registers RDI, RSI, RDX, RCX,
R8, R9, then compiler may keep arguments in the same registers without
any spilling to the stack]
>
>> /**
>> * Convert datetime to string using default asctime format
>> * "Sun Sep 16 01:03:52 1973\n\0"
>> diff --git a/src/lua/datetime.lua b/src/lua/datetime.lua
>> index ce579828f..4d946f194 100644
>> --- a/src/lua/datetime.lua
>> +++ b/src/lua/datetime.lua
>> @@ -249,6 +249,37 @@ local function datetime_new(obj)
>> return datetime_new_dt(dt, secs, frac, offset)
>> end
>>
>> +local function datetime_tostring(o)
>
> Please add a comment to this function with example output.
Documented.
>
>> + if ffi.typeof(o) == datetime_t then
>> + local sz = 48
>> + local buff = ffi.new('char[?]', sz)
>> + local len = builtin.datetime_to_string(o, buff, sz)
>> + assert(len < sz)
>> + return ffi.string(buff)
>> + elseif ffi.typeof(o) == interval_t then
>
> Please define separate functions for interval and datetime.
Yes, that will simplify. Part of a corresponding diff below...
----------------------------------------
@@ -373,9 +366,16 @@ local function datetime_new(obj)
secs = h * 3600 + m * 60 + s
end
- return datetime_new_dt(dt, secs, frac, offset)
+ return datetime_new_dt(dt, secs, nsec, offset)
end
+--[[
+ Convert to text datetime values
+
+ - datetime will use ISO-8601 forat:
+ 1970-01-01T00:00Z
+ 2021-08-18T16:57:08.981725+03:00
+]]
local function datetime_tostring(o)
if ffi.typeof(o) == datetime_t then
local sz = 48
@@ -383,7 +383,25 @@ local function datetime_tostring(o)
local len = builtin.datetime_to_string(o, buff, sz)
assert(len < sz)
return ffi.string(buff)
- elseif ffi.typeof(o) == interval_years_t then
+ end
+end
+
+--[[
+ Convert to text interval values of different types
+
+ - depending on a values stored there generic interval
+ values may display in following format:
+ +12 secs
+ -23 minutes, 0 seconds
+ +12 hours, 23 minutes, 1 seconds
+ -7 days, 23 hours, 23 minutes, 1 seconds
+ - years will be displayed as
+ +10 years
+ - months will be displayed as:
+ +2 months
+]]
+local function interval_tostring(o)
+ if ffi.typeof(o) == interval_years_t then
return ('%+d years'):format(o.y)
elseif ffi.typeof(o) == interval_months_t then
return ('%+d months'):format(o.m)
@@ -828,7 +901,7 @@ local datetime_mt = {
}
local interval_mt = {
- __tostring = datetime_tostring,
+ __tostring = interval_tostring,
__serialize = interval_serialize,
__eq = datetime_eq,
__lt = datetime_lt,
@@ -839,7 +912,7 @@ local interval_mt = {
}
local interval_tiny_mt = {
- __tostring = datetime_tostring,
+ __tostring = interval_tostring,
__serialize = interval_serialize,
__sub = datetime_sub,
__add = datetime_add,
----------------------------------------
>
>> + local ts = o.timestamp
>> + local sign = '+'
>> +
>> + if ts < 0 then
>> + ts = -ts
>> + sign = '-'
>> + end
>> +
>> + if ts < 60 then
>> + return ('%s%s secs'):format(sign, ts)
>> + elseif ts < 60 * 60 then
>> + return ('%+d minutes, %s seconds'):format(o.minutes, ts %
> 60)
>> + elseif ts < 24 * 60 * 60 then
>> + return ('%+d hours, %d minutes, %s seconds'):format(
>> + o.hours, o.minutes % 60, ts % 60)
>> + else
>> + return ('%+d days, %d hours, %d minutes, %s
> seconds'):format(
>> + o.days, o.hours % 24, o.minutes % 60, ts % 60)
>> + end
>> + end
>> +end
>> +
>> +
>> --[[
>> Basic Extended
>> 20121224 2012-12-24 Calendar date (ISO 8601)
>> @@ -457,6 +488,7 @@ local function strftime(fmt, o)
>> end
>>
>> local datetime_mt = {
>> + __tostring = datetime_tostring,
>> __serialize = datetime_serialize,
>> __eq = datetime_eq,
>> __lt = datetime_lt,
>> @@ -466,6 +498,7 @@ local datetime_mt = {
>> }
>>
>> local interval_mt = {
>> + __tostring = datetime_tostring,
>> __serialize = interval_serialize,
>> __eq = datetime_eq,
>> __lt = datetime_lt,
>> @@ -487,6 +520,8 @@ return setmetatable(
>> parse_time = parse_time,
>> parse_zone = parse_zone,
>>
>> + tostring = datetime_tostring,
>> +
>
> I don't think we need this function in the module. Global tostring() is
> enough.
>
-----------------------------------------
@@ -862,15 +935,12 @@ return setmetatable(
hours = interval_hours_new,
minutes = interval_minutes_new,
seconds = interval_seconds_new,
- interval = interval_new,
parse = parse,
parse_date = parse_date,
parse_time = parse_time,
parse_zone = parse_zone,
- tostring = datetime_tostring,
-
now = local_now,
strftime = strftime,
asctime = asctime,
-----------------------------------------
Deleted.
Thanks,
Timur
next prev parent reply other threads:[~2021-08-18 14:11 UTC|newest]
Thread overview: 50+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-08-15 23:59 [Tarantool-patches] [PATCH v5 0/8] Initial datetime implementation Timur Safin via Tarantool-patches
2021-08-15 23:59 ` [Tarantool-patches] [PATCH v5 1/8] build: add Christian Hansen c-dt to the build Timur Safin via Tarantool-patches
2021-08-17 12:15 ` Serge Petrenko via Tarantool-patches
2021-08-17 23:24 ` Safin Timur via Tarantool-patches
2021-08-18 8:56 ` Serge Petrenko via Tarantool-patches
2021-08-17 15:50 ` Vladimir Davydov via Tarantool-patches
2021-08-18 10:04 ` Safin Timur via Tarantool-patches
2021-08-15 23:59 ` [Tarantool-patches] [PATCH v5 2/8] lua: built-in module datetime Timur Safin via Tarantool-patches
2021-08-17 12:15 ` Serge Petrenko via Tarantool-patches
2021-08-17 23:30 ` Safin Timur via Tarantool-patches
2021-08-18 8:56 ` Serge Petrenko via Tarantool-patches
2021-08-17 16:52 ` Vladimir Davydov via Tarantool-patches
2021-08-17 19:16 ` Vladimir Davydov via Tarantool-patches
2021-08-18 13:38 ` Safin Timur via Tarantool-patches
2021-08-18 10:03 ` Safin Timur via Tarantool-patches
2021-08-18 10:06 ` Safin Timur via Tarantool-patches
2021-08-18 11:45 ` Vladimir Davydov via Tarantool-patches
2021-08-15 23:59 ` [Tarantool-patches] [PATCH v5 3/8] lua, datetime: display datetime Timur Safin via Tarantool-patches
2021-08-17 12:15 ` Serge Petrenko via Tarantool-patches
2021-08-17 23:32 ` Safin Timur via Tarantool-patches
2021-08-17 17:06 ` Vladimir Davydov via Tarantool-patches
2021-08-18 14:10 ` Safin Timur via Tarantool-patches [this message]
2021-08-15 23:59 ` [Tarantool-patches] [PATCH v5 4/8] box, datetime: messagepack support for datetime Timur Safin via Tarantool-patches
2021-08-16 0:20 ` Safin Timur via Tarantool-patches
2021-08-17 12:15 ` Serge Petrenko via Tarantool-patches
2021-08-17 12:16 ` Serge Petrenko via Tarantool-patches
2021-08-17 23:42 ` Safin Timur via Tarantool-patches
2021-08-18 9:01 ` Serge Petrenko via Tarantool-patches
2021-08-17 18:36 ` Vladimir Davydov via Tarantool-patches
2021-08-18 14:27 ` Safin Timur via Tarantool-patches
2021-08-15 23:59 ` [Tarantool-patches] [PATCH v5 5/8] box, datetime: datetime comparison for indices Timur Safin via Tarantool-patches
2021-08-17 12:16 ` Serge Petrenko via Tarantool-patches
2021-08-17 23:43 ` Safin Timur via Tarantool-patches
2021-08-18 9:03 ` Serge Petrenko via Tarantool-patches
2021-08-17 19:05 ` Vladimir Davydov via Tarantool-patches
2021-08-18 17:18 ` Safin Timur via Tarantool-patches
2021-08-15 23:59 ` [Tarantool-patches] [PATCH v5 6/8] lua, datetime: time intervals support Timur Safin via Tarantool-patches
2021-08-17 12:16 ` Serge Petrenko via Tarantool-patches
2021-08-17 23:44 ` Safin Timur via Tarantool-patches
2021-08-17 18:52 ` Vladimir Davydov via Tarantool-patches
2021-08-15 23:59 ` [Tarantool-patches] [PATCH v5 7/8] datetime: perf test for datetime parser Timur Safin via Tarantool-patches
2021-08-17 19:13 ` Vladimir Davydov via Tarantool-patches
2021-08-15 23:59 ` [Tarantool-patches] [PATCH v5 8/8] datetime: changelog for datetime module Timur Safin via Tarantool-patches
2021-08-17 12:16 ` Serge Petrenko via Tarantool-patches
2021-08-17 23:44 ` Safin Timur via Tarantool-patches
2021-08-18 9:04 ` Serge Petrenko via Tarantool-patches
2021-08-17 12:15 ` [Tarantool-patches] [PATCH v5 0/8] Initial datetime implementation Serge Petrenko via Tarantool-patches
[not found] ` <20210818082222.mofgheciutpipelz@esperanza>
2021-08-18 8:25 ` Vladimir Davydov via Tarantool-patches
2021-08-18 13:24 ` Safin Timur via Tarantool-patches
2021-08-18 14:22 ` Vladimir Davydov via Tarantool-patches
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=b9f86b63-9a6d-c7a8-b365-0d30eaf4b4c7@tarantool.org \
--to=tarantool-patches@dev.tarantool.org \
--cc=tsafin@tarantool.org \
--cc=v.shpilevoy@tarantool.org \
--cc=vdavydov@tarantool.org \
--subject='Re: [Tarantool-patches] [PATCH v5 3/8] lua, datetime: display datetime' \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox