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 E7BA66EC6E; Wed, 28 Jul 2021 13:38:58 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org E7BA66EC6E DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=tarantool.org; s=dev; t=1627468739; bh=6q9tQetkcFK2px60deJ/WpY1TfFaapITjnegLAGJxZ0=; h=To:Date:In-Reply-To:References:Subject:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=J1TD2PxAQlHD3OJeVurLn7Lnxj8YaD31hSHHhYiWo+QjUCXOlEDP61+BR/wSu9pYC PzgMvgeWTxfNdSPbInxWmM9IMa1uoZ5qXjZKTrHPVGyMpdElhhgzKkAJEm8AaQXzue XGRQi/x9OCqXbowp/TV26l1QhsjVa5OF7Hmho4jw= Received: from smtp57.i.mail.ru (smtp57.i.mail.ru [217.69.128.37]) (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 57EFB6EC7F for ; Wed, 28 Jul 2021 13:34:38 +0300 (MSK) DKIM-Filter: OpenDKIM Filter v2.11.0 dev.tarantool.org 57EFB6EC7F Received: by smtp57.i.mail.ru with esmtpa (envelope-from ) id 1m8gtX-0008Bz-VQ; Wed, 28 Jul 2021 13:34:36 +0300 To: v.shpilevoy@tarantool.org Date: Wed, 28 Jul 2021 13:34:12 +0300 Message-Id: X-Mailer: git-send-email 2.29.2 In-Reply-To: References: MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-4EC0790: 10 X-7564579A: 646B95376F6C166E X-77F55803: 4F1203BC0FB41BD941C43E597735A9C36A98DBA789EBB6AE26DB9A6C1D9BF7E0182A05F5380850404D063AF24BD8C50FDF7922F5774BCC9F698365E2A05B3CE5A1C0C4C781B50F88 X-7FA49CB5: FF5795518A3D127A4AD6D5ED66289B5278DA827A17800CE728F774C865CF4B07EA1F7E6F0F101C67BD4B6F7A4D31EC0BCC500DACC3FED6E28638F802B75D45FF8AA50765F790063729381D024F10DD158638F802B75D45FF36EB9D2243A4F8B5A6FCA7DBDB1FC311F39EFFDF887939037866D6147AF826D85791656B090F33D704C2750679634ED4117882F4460429724CE54428C33FAD305F5C1EE8F4F765FCAA867293B0326636D2E47CDBA5A96583BD4B6F7A4D31EC0BC014FD901B82EE079FA2833FD35BB23D27C277FBC8AE2E8BAA867293B0326636D2E47CDBA5A96583BA9C0B312567BB2376E601842F6C81A19E625A9149C048EE7532CA1512B81981D7C2347B1D03E769D8FC6C240DEA7642DBF02ECDB25306B2B78CF848AE20165D0A6AB1C7CE11FEE36633242DC033995003F1AB874ED89028C4224003CC836476EA7A3FFF5B025636E2021AF6380DFAD1A18204E546F3947CB11811A4A51E3B096D1867E19FE1407959CC434672EE6371089D37D7C0E48F6C8AA50765F7900637B8F435DEDE9E76EBEFF80C71ABB335746BA297DBC24807EABDAD6C7F3747799A X-C1DE0DAB: C20DE7B7AB408E4181F030C43753B8186998911F362727C414F749A5E30D975C7BEA09003D200E08C08FD45B7F8344A61F291A5A8EBF7D4D9C2B6934AE262D3EE7EAB7254005DCED7532B743992DF240BDC6A1CF3F042BAD6DF99611D93F60EF824747F4BD2CC0FE699F904B3F4130E343918A1A30D5E7FCCB5012B2E24CD356 X-C8649E89: 4E36BF7865823D7055A7F0CF078B5EC49A30900B95165D3475AE8838CC1BF58E5811E080D67F6DDB39060AF04CC82B12B6E65DD46126DA6396F0E9ABC6707E3D1D7E09C32AA3244CA30008953E0DE06BBB7B6606B5A5F2293FD9C8CA1B0515E083B48618A63566E0 X-D57D3AED: 3ZO7eAau8CL7WIMRKs4sN3D3tLDjz0dLbV79QFUyzQ2Ujvy7cMT6pYYqY16iZVKkSc3dCLJ7zSJH7+u4VD18S7Vl4ZUrpaVfd2+vE6kuoey4m4VkSEu530nj6fImhcD4MUrOEAnl0W826KZ9Q+tr5ycPtXkTV4k65bRjmOUUP8cvGozZ33TWg5HZplvhhXbhDGzqmQDTd6OAevLeAnq3Ra9uf7zvY2zzsIhlcp/Y7m53TZgf2aB4JOg4gkr2biojiF1u9eOpfTRuq/43mKj08A== X-Mailru-Sender: B5B6A6EBBD94DAD8C47A93838048902D54E8C5C2A129CF37FF6D64C575892A2833C53C74A7ED986F1EC9E4A2C82A33BC8C24925A86E657CE0C70AEE3C9A96FBAB3D7EE8ED63280BE112434F685709FCF0DA7A0AF5A3A8387 X-Mras: Ok Subject: [Tarantool-patches] [PATCH resend v2 10/11] lua, datetime: unixtime, timestamp setters in datetime.lua 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: Timur Safin via Tarantool-patches Reply-To: Timur Safin Cc: tarantool-patches@dev.tarantool.org Errors-To: tarantool-patches-bounces@dev.tarantool.org Sender: "Tarantool-patches" * implemented proper range checks for date attributes values; * created `.unixtime` attribute, which is alias to `.secs`, with corresponding setter/getter; * similarly to `unixtime`, created virtual `timestamp` attribute setter. Which is a convenient way to simultaneously assign unixtime (seconds since epoch) and nanoseconds Part of #5941 --- src/lua/datetime.lua | 90 ++++++++++++++++++++++++++++++-------------- 1 file changed, 61 insertions(+), 29 deletions(-) diff --git a/src/lua/datetime.lua b/src/lua/datetime.lua index 1466b923f..cc2ae119b 100644 --- a/src/lua/datetime.lua +++ b/src/lua/datetime.lua @@ -342,12 +342,33 @@ local function _normalize_nsec(secs, nsec) return secs, nsec end +local function seconds_fraction(v) + local seconds, fraction + fraction = v % 1 + if fraction > 0 then + seconds = v - (v % 1) + else + seconds = v + end + return seconds, fraction +end + +local function check_range(v, range, txt) + assert(#range == 2) + if not (v >= range[1] and v <= range[2]) then + error(('value %d of %s is out of allowed range [%d, %d]'): + format(v, txt, range[1], range[2])) + end +end + -- addition or subtraction from date/time of a given interval -- described via table direction should be +1 or -1 local function interval_increment(self, o, direction) assert(direction == -1 or direction == 1) - check_date(self, "interval_increment(date, object, -+1)") - assert(type(o) == 'table') + check_date(self, "interval_increment(date, object, direction)") + if type(o) ~= 'table' then + error('interval_increment(date, object, direction) - object expected', 2) + end local ym_updated = false local dhms_updated = false @@ -359,49 +380,43 @@ local function interval_increment(self, o, direction) for key, value in pairs(o) do local handlers = { years = function(v) - assert(v > 0 and v < 10000) + check_range(v, {0, 9999}, key) dt = cdt.dt_add_years(dt, direction * v, cdt.DT_LIMIT) ym_updated = true end, months = function(v) - assert(v > 0 and v < 13 ) + check_range(v, {0, 12}, key) dt = cdt.dt_add_months(dt, direction * v, cdt.DT_LIMIT) ym_updated = true end, weeks = function(v) - assert(v > 0 and v < 32) + check_range(v, {0, 52}, key) secs = secs + direction * 7 * v * SECS_PER_DAY dhms_updated = true end, days = function(v) - assert(v > 0 and v < 32) + check_range(v, {0, 31}, key) secs = secs + direction * v * SECS_PER_DAY dhms_updated = true end, hours = function(v) - assert(v >= 0 and v < 24) + check_range(v, {0, 23}, key) secs = secs + direction * 60 * 60 * v dhms_updated = true end, minutes = function(v) - assert(v >= 0 and v < 60) + check_range(v, {0, 59}, key) secs = secs + direction * 60 * v end, seconds = function(v) - assert(v >= 0 and v < 61) - local s, frac - frac = v % 1 - if frac > 0 then - s = v - (v % 1) - else - s = v - end + check_range(v, {0, 60}, key) + local s, frac = seconds_fraction(v) secs = secs + direction * s nsec = nsec + direction * frac * 1e9 -- convert fraction to nanoseconds dhms_updated = true @@ -429,6 +444,9 @@ end local datetime_index = function(self, key) local attributes = { + unixtime = function(self) + return self.secs + end, timestamp = function(self) return tonumber(self.secs) + self.nsec / 1e9 end, @@ -467,6 +485,24 @@ local datetime_index = function(self, key) return attributes[key] ~= nil and attributes[key](self) or nil end +local function datetime_newindex(self, key, value) + local attributes = { + unixtime = function(self, value) + self.secs = value + self.nsec, self.offset = 0, 0 + end, + timestamp = function(self, value) + local secs, frac = seconds_fraction(value) + self.secs = secs + self.nsec = frac * 1e9 + self.offset = 0 + end, + } + if attributes[key] ~= nil then + attributes[key](self, value) + end +end + local function datetime_new_raw(secs, nsec, offset) local dt_obj = ffi.new(datetime_t) dt_obj.secs = secs @@ -518,50 +554,45 @@ local function datetime_new(o) end, year = function(v) - assert(v > 0 and v < 10000) + check_range(v, {1, 9999}, key) y = v ymd = true end, month = function(v) - assert(v > 0 and v < 13 ) + check_range(v, {1, 12}, key) M = v ymd = true end, day = function(v) - assert(v > 0 and v < 32) + check_range(v, {1, 31}, key) d = v ymd = true end, hour = function(v) - assert(v >= 0 and v < 24) + check_range(v, {0, 23}, key) h = v hms = true end, minute = function(v) - assert(v >= 0 and v < 60) + check_range(v, {0, 59}, key) m = v hms = true end, second = function(v) - assert(v >= 0 and v < 61) - frac = v % 1 - if frac > 0 then - s = v - (v % 1) - else - s = v - end + check_range(v, {0, 60}, key) + s, frac = seconds_fraction(v) frac = frac * 1e9 -- convert fraction to nanoseconds hms = true end, -- tz offset in minutes tz = function(v) - assert(v >= 0 and v <= 720) + check_range(v, {0, 720}, key) offset = v end } @@ -918,6 +949,7 @@ local datetime_mt = { __sub = datetime_sub, __add = datetime_add, __index = datetime_index, + __newindex = datetime_newindex, add = function(self, o) self = interval_increment(self, o, 1) return self -- 2.29.2