diff --git a/features/dates.feature b/features/dates.feature index cb4db436..ba86b224 100644 --- a/features/dates.feature +++ b/features/dates.feature @@ -75,33 +75,33 @@ Feature: Processing of (relative) dates and times Examples: short months | 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 | | mar | 2014-03-01 09:00 | 35 | - | apr | 2014-04-01 09:00 | 36 | - | may | 2014-05-01 09:00 | 37 | - | jun | 2014-06-01 09:00 | 38 | - | jul | 2014-07-01 09:00 | 39 | - | aug | 2014-08-01 09:00 | 40 | - | sep | 2014-09-01 09:00 | 41 | - | oct | 2014-10-01 09:00 | 42 | - | nov | 2014-11-01 09:00 | 43 | - | dec | 2014-12-01 09:00 | 44 | - | sept | 2014-09-01 09:00 | 45 | + | apr | 2013-04-01 09:00 | 36 | + | may | 2013-05-01 09:00 | 37 | + | jun | 2013-06-01 09:00 | 38 | + | jul | 2013-07-01 09:00 | 39 | + | aug | 2013-08-01 09:00 | 40 | + | sep | 2013-09-01 09:00 | 41 | + | oct | 2013-10-01 09:00 | 42 | + | nov | 2013-11-01 09:00 | 43 | + | dec | 2013-12-01 09:00 | 44 | + | sept | 2013-09-01 09:00 | 45 | Examples: long months | 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 | | march | 2014-03-01 09:00 | 48 | - | april | 2014-04-01 09:00 | 49 | - | june | 2014-06-01 09:00 | 50 | - | july | 2014-07-01 09:00 | 51 | - | august | 2014-08-01 09:00 | 52 | - | september | 2014-09-01 09:00 | 53 | - | october | 2014-10-01 09:00 | 54 | - | november | 2014-11-01 09:00 | 55 | - | december | 2014-12-01 09:00 | 56 | + | april | 2013-04-01 09:00 | 49 | + | june | 2013-06-01 09:00 | 50 | + | july | 2013-07-01 09:00 | 51 | + | august | 2013-08-01 09:00 | 52 | + | september | 2013-09-01 09:00 | 53 | + | october | 2013-10-01 09:00 | 54 | + | november | 2013-11-01 09:00 | 55 | + | december | 2013-12-01 09:00 | 56 | Examples: month + day (no year) # unless within 28 days, assumed to be the last occurance diff --git a/features/dates2.feature b/features/dates2.feature index 59ca8d4c..1b51e55b 100644 --- a/features/dates2.feature +++ b/features/dates2.feature @@ -1,5 +1,5 @@ -@dates2 @dates @wip +@dates2 @dates Feature: Processing of (fixed) dates and times Scenario Outline: Test all sorts of (fixed) dates diff --git a/jrnl/Journal.py b/jrnl/Journal.py index cbf754a2..4fc62d02 100644 --- a/jrnl/Journal.py +++ b/jrnl/Journal.py @@ -11,6 +11,7 @@ try: except ImportError: import parsedatetime as pdt import re +from datetime import timedelta from datetime import datetime import dateutil import time @@ -254,44 +255,92 @@ class Journal(object): # Use the default time. date = datetime(year=int(date_str), month=1, day=1, hour=self.config['default_hour'], minute=self.config['default_minute']) else: + # clean up some misunderstood dates 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" o'clock", u":00") date_str = util.multiple_replace(date_str, *replacements) - try: - date = dateutil.parser.parse(date_str) - flag = 1 if date.hour == 0 and date.minute == 0 else 2 - date = date.timetuple() - except: - date, flag = self.dateparse.parse(date_str) + # determine if we've been given just a month, or just a year and month + replacements2 = ("january", "01"), ("february", "02"), ("march", "03"), \ + ("april", "04"), ("may", "05"), ("june", "06"), \ + ("july", "07"), ("august", "08"), \ + ("october", "10"), ("november", "11"), ("december", "12"), \ + ("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. - 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 given (just) a month and it's not this month or next, assume it was last year + dt = datetime.now() - datetime(year=int(myYear), month=int(myMonth), day=1) + if dt.days < -32: + myYear = myYear - 1 + year_month_only = True - if flag is 1: # Date found, but no time. + if year_month_only == True: 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": - 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: # Use the default time. - date = datetime(*date[:3], hour=self.config['default_hour'], minute=self.config['default_minute']) - else: - date = datetime(*date[:6]) + date = datetime(year=int(myYear), month=int(myMonth), day=1, hour=self.config['default_hour'], minute=self.config['default_minute']) - # 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) + else: + try: + date = dateutil.parser.parse(date_str) + flag = 1 if date.hour == 0 and date.minute == 0 else 2 + date = date.timetuple() + 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