Skip to content

Commit d7b479c

Browse files
committed
supporting round up and round down
For example, the expression `from: "now/d", until: "now/d"` in ElasticSearch will be translate into starts from 00:00:00 and ends at 23:59:59. There is not way to distinguish these two case, so add another argument `roundDown` to specified the method when rounding date, default value is True, which means 'floor'.
1 parent e152a89 commit d7b479c

File tree

2 files changed

+22
-6
lines changed

2 files changed

+22
-6
lines changed

datemath/helpers.py

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ def as_datetime(expression, now, tz='UTC'):
7676
'''
7777
return parse(expression, now, tz)
7878

79-
def parse(expression, now=None, tz='UTC', type=None):
79+
def parse(expression, now=None, tz='UTC', type=None, roundDown=True):
8080
'''
8181
the main meat and potatoes of this this whole thing
8282
takes our datemath expression and does our date math
@@ -123,7 +123,7 @@ def parse(expression, now=None, tz='UTC', type=None):
123123
if not math or math == '':
124124
rettime = time
125125

126-
rettime = evaluate(math, time, tz)
126+
rettime = evaluate(math, time, tz, roundDown)
127127
if type:
128128
return getattr(rettime, type)
129129
else:
@@ -139,11 +139,14 @@ def parseTime(timestamp, tz='UTC'):
139139
return arrow.get(timestamp)
140140

141141

142-
def roundDate(now, unit, tz='UTC'):
142+
def roundDate(now, unit, tz='UTC', roundDown=True):
143143
'''
144144
rounds our date object
145145
'''
146-
now = now.floor(unit)
146+
if roundDown:
147+
now = now.floor(unit)
148+
else:
149+
now = now.ceil(unit)
147150
if debug: print("roundDate Now: {0}".format(now))
148151
return now
149152

@@ -161,7 +164,7 @@ def calculate(now, offsetval, unit):
161164
except Exception as e:
162165
raise DateMathException('Unable to calculate date: now: {0}, offsetvalue: {1}, unit: {2} - reason: {3}'.format(now,offsetval,unit,e))
163166

164-
def evaluate(expression, now, timeZone='UTC'):
167+
def evaluate(expression, now, timeZone='UTC', roundDown=True):
165168
'''
166169
evaluates our datemath style expression
167170
'''
@@ -176,7 +179,7 @@ def evaluate(expression, now, timeZone='UTC'):
176179
# then we need to round
177180
next = str(expression[i+1])
178181
i += 1
179-
now = roundDate(now, unitMap(next).rstrip('s'), timeZone)
182+
now = roundDate(now, unitMap(next).rstrip('s'), timeZone, roundDown)
180183

181184
elif char == '+' or char == '-':
182185
val = 0

tests.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ def testParse(self):
2323
self.assertEqual(dm('2016-01-02T14:02:00||/h').format(iso8601), '2016-01-02T14:00:00-00:00')
2424
self.assertEqual(dm('2016-01-02T14:02:00||/H').format(iso8601), '2016-01-02T14:00:00-00:00')
2525

26+
# Rounding Up Tests
27+
self.assertEqual(dm('2016-01-01||/d', roundDown=False).format('YYYY-MM-DDTHH:mm:ssZZ'), '2016-01-01T23:59:59-00:00')
28+
self.assertEqual(dm('2014-11-18||/y', roundDown=False).format('YYYY-MM-DDTHH:mm:ssZZ'), '2014-12-31T23:59:59-00:00')
29+
2630
# relitive formats
2731
# addition
2832
self.assertEqual(dm('+1s').format(iso8601), arrow.utcnow().replace(seconds=+1).format(iso8601))
@@ -51,6 +55,15 @@ def testParse(self):
5155
self.assertEqual(dm('/M').format(iso8601), arrow.utcnow().floor('month').format(iso8601))
5256
self.assertEqual(dm('/Y').format(iso8601), arrow.utcnow().floor('year').format(iso8601))
5357
self.assertEqual(dm('/y').format(iso8601), arrow.utcnow().floor('year').format(iso8601))
58+
# rounding up
59+
self.assertEqual(dm('/s', roundDown=False).format(iso8601), arrow.utcnow().ceil('second').format(iso8601))
60+
self.assertEqual(dm('/m', roundDown=False).format(iso8601), arrow.utcnow().ceil('minute').format(iso8601))
61+
self.assertEqual(dm('/h', roundDown=False).format(iso8601), arrow.utcnow().ceil('hour').format(iso8601))
62+
self.assertEqual(dm('/d', roundDown=False).format(iso8601), arrow.utcnow().ceil('day').format(iso8601))
63+
self.assertEqual(dm('/w', roundDown=False).format(iso8601), arrow.utcnow().ceil('week').format(iso8601))
64+
self.assertEqual(dm('/M', roundDown=False).format(iso8601), arrow.utcnow().ceil('month').format(iso8601))
65+
self.assertEqual(dm('/Y', roundDown=False).format(iso8601), arrow.utcnow().ceil('year').format(iso8601))
66+
self.assertEqual(dm('/y', roundDown=False).format(iso8601), arrow.utcnow().ceil('year').format(iso8601))
5467
# complicated date math
5568
self.assertEqual(dm('now/d-1h').format(iso8601), arrow.utcnow().floor('day').replace(hours=-1).format(iso8601))
5669
self.assertEqual(dm('+1h').format(iso8601), arrow.utcnow().replace(hours=+1).format(iso8601))

0 commit comments

Comments
 (0)