deal with months

allow `-to` and `-from` to work on bare months; also if just a month is
given for an entry, assume the default time on the 1st of the month.
This commit is contained in:
William Minchin 2014-02-10 13:24:42 -07:00
parent b0a29736d7
commit 9652575928
3 changed files with 96 additions and 47 deletions

View file

@ -75,33 +75,33 @@ Feature: Processing of (relative) dates and times
Examples: short months Examples: short months
| date in | date out | entry no | | date in | date out | entry no |
| jan | 2015-01-01 09:00 | 33 | | jan | 2014-01-01 09:00 | 33 |
| feb | 2014-02-01 09:00 | 34 | | feb | 2014-02-01 09:00 | 34 |
| mar | 2014-03-01 09:00 | 35 | | mar | 2014-03-01 09:00 | 35 |
| apr | 2014-04-01 09:00 | 36 | | apr | 2013-04-01 09:00 | 36 |
| may | 2014-05-01 09:00 | 37 | | may | 2013-05-01 09:00 | 37 |
| jun | 2014-06-01 09:00 | 38 | | jun | 2013-06-01 09:00 | 38 |
| jul | 2014-07-01 09:00 | 39 | | jul | 2013-07-01 09:00 | 39 |
| aug | 2014-08-01 09:00 | 40 | | aug | 2013-08-01 09:00 | 40 |
| sep | 2014-09-01 09:00 | 41 | | sep | 2013-09-01 09:00 | 41 |
| oct | 2014-10-01 09:00 | 42 | | oct | 2013-10-01 09:00 | 42 |
| nov | 2014-11-01 09:00 | 43 | | nov | 2013-11-01 09:00 | 43 |
| dec | 2014-12-01 09:00 | 44 | | dec | 2013-12-01 09:00 | 44 |
| sept | 2014-09-01 09:00 | 45 | | sept | 2013-09-01 09:00 | 45 |
Examples: long months Examples: long months
| date in | date out | entry no | | date in | date out | entry no |
| january | 2015-01-01 09:00 | 46 | | january | 2014-01-01 09:00 | 46 |
| february | 2014-02-01 09:00 | 47 | | february | 2014-02-01 09:00 | 47 |
| march | 2014-03-01 09:00 | 48 | | march | 2014-03-01 09:00 | 48 |
| april | 2014-04-01 09:00 | 49 | | april | 2013-04-01 09:00 | 49 |
| june | 2014-06-01 09:00 | 50 | | june | 2013-06-01 09:00 | 50 |
| july | 2014-07-01 09:00 | 51 | | july | 2013-07-01 09:00 | 51 |
| august | 2014-08-01 09:00 | 52 | | august | 2013-08-01 09:00 | 52 |
| september | 2014-09-01 09:00 | 53 | | september | 2013-09-01 09:00 | 53 |
| october | 2014-10-01 09:00 | 54 | | october | 2013-10-01 09:00 | 54 |
| november | 2014-11-01 09:00 | 55 | | november | 2013-11-01 09:00 | 55 |
| december | 2014-12-01 09:00 | 56 | | december | 2013-12-01 09:00 | 56 |
Examples: month + day (no year) Examples: month + day (no year)
# unless within 28 days, assumed to be the last occurance # unless within 28 days, assumed to be the last occurance

View file

@ -1,5 +1,5 @@
@dates2 @dates @wip @dates2 @dates
Feature: Processing of (fixed) dates and times Feature: Processing of (fixed) dates and times
Scenario Outline: Test all sorts of (fixed) dates Scenario Outline: Test all sorts of (fixed) dates

View file

@ -11,6 +11,7 @@ try:
except ImportError: except ImportError:
import parsedatetime as pdt import parsedatetime as pdt
import re import re
from datetime import timedelta
from datetime import datetime from datetime import datetime
import dateutil import dateutil
import time import time
@ -254,44 +255,92 @@ class Journal(object):
# Use the default time. # Use the default time.
date = datetime(year=int(date_str), month=1, day=1, hour=self.config['default_hour'], minute=self.config['default_minute']) date = datetime(year=int(date_str), month=1, day=1, hour=self.config['default_hour'], minute=self.config['default_minute'])
else: else:
# clean up some misunderstood dates
replacements = (u"september", u"sep"), (u"sept", u"sep"), (u"tuesday", u"tue"), \ replacements = (u"september", u"sep"), (u"sept", u"sep"), (u"tuesday", u"tue"), \
(u"tues", u"tue"), (u"thursday", u"thu"), (u"thurs", u"thu"), \ (u"tues", u"tue"), (u"thursday", u"thu"), (u"thurs", u"thu"), \
(u" o'clock", u":00") (u" o'clock", u":00")
date_str = util.multiple_replace(date_str, *replacements) date_str = util.multiple_replace(date_str, *replacements)
try: # determine if we've been given just a month, or just a year and month
date = dateutil.parser.parse(date_str) replacements2 = ("january", "01"), ("february", "02"), ("march", "03"), \
flag = 1 if date.hour == 0 and date.minute == 0 else 2 ("april", "04"), ("may", "05"), ("june", "06"), \
date = date.timetuple() ("july", "07"), ("august", "08"), \
except: ("october", "10"), ("november", "11"), ("december", "12"), \
date, flag = self.dateparse.parse(date_str) ("jan", "01"), ("feb", "02"), ("mar", "03"), ("apr", "04"), \
("jun", "06"), ("jul", "07"), ("aug", "08"), \
("sep", "09"), ("oct", "10"), ("nov", "11"), ("dec", "12")
date_str2 = util.multiple_replace(date_str, *replacements2)
year_month_only = False;
matches = re.match(r'^(\d{4})[ \\/-](\d{2})$', date_str2)
if matches:
myYear = matches.group(1)
myMonth = matches.group(2)
year_month_only = True
else:
matches2 = re.match(r'^(\d{2})[ \\/-](\d{4})$', date_str2)
if matches2:
myYear = matches2.group(2)
myMonth = matches2.group(1)
year_month_only = True
else:
matches3 = re.match(r'^(\d{2})$', date_str2)
if matches3:
myYear = datetime.today().year
myMonth = matches3.group(0)
if not flag: # Oops, unparsable. # if given (just) a month and it's not this month or next, assume it was last year
try: # Try and parse this as a single year dt = datetime.now() - datetime(year=int(myYear), month=int(myMonth), day=1)
year = int(date_str) if dt.days < -32:
return datetime(year, 1, 1) myYear = myYear - 1
except ValueError: year_month_only = True
return None
except TypeError:
return None
if flag is 1: # Date found, but no time. if year_month_only == True:
if end_flag == "from": if end_flag == "from":
date = datetime(*date[:3], hour=0, minute=0) date = datetime(year=int(myYear), month=int(myMonth), day=1, hour=0, minute=0)
elif end_flag == "to": elif end_flag == "to":
date = datetime(*date[:3], hour=23, minute=59, second=59) # get the last day of the month
if myMouth == 12:
date = datetime(year=int(myYear), month=int(myMonth), day=31, hour=23, minute=59, second=59)
else:
date = datetime(year=int(myYear), month=int(myMonth)+1, day=1, hour=23, minute=59, second=59) - timedelta (days = 1)
else: else:
# Use the default time. # Use the default time.
date = datetime(*date[:3], hour=self.config['default_hour'], minute=self.config['default_minute']) date = datetime(year=int(myYear), month=int(myMonth), day=1, hour=self.config['default_hour'], minute=self.config['default_minute'])
else:
date = datetime(*date[:6])
# Ugly heuristic: if the date is more than 4 weeks in the future, we got the year wrong. else:
# Rather then this, we would like to see parsedatetime patched so we can tell it to prefer try:
# past dates date = dateutil.parser.parse(date_str)
dt = datetime.now() - date flag = 1 if date.hour == 0 and date.minute == 0 else 2
if dt.days < -28: date = date.timetuple()
date = date.replace(date.year - 1) except:
date, flag = self.dateparse.parse(date_str)
if not flag: # Oops, unparsable.
try: # Try and parse this as a single year
year = int(date_str)
return datetime(year, 1, 1)
except ValueError:
return None
except TypeError:
return None
if flag is 1: # Date found, but no time.
if end_flag == "from":
date = datetime(*date[:3], hour=0, minute=0)
elif end_flag == "to":
date = datetime(*date[:3], hour=23, minute=59, second=59)
else:
# Use the default time.
date = datetime(*date[:3], hour=self.config['default_hour'], minute=self.config['default_minute'])
else:
date = datetime(*date[:6])
# Ugly heuristic: if the date is more than 4 weeks in the future, we got the year wrong.
# Rather then this, we would like to see parsedatetime patched so we can tell it to prefer
# past dates
dt = datetime.now() - date
if dt.days < -28:
date = date.replace(date.year - 1)
return date return date