comparison mercurial/util.py @ 13212:5d0a30fad7de stable

date: fix matching of underspecified date ranges (backport of 91bc001a592f to stable)
author Matt Mackall <mpm@selenic.com>
date Wed, 29 Dec 2010 14:19:31 -0600
parents 5b83ab614dab
children 3eee7b42d17e e3bf16703e26
comparison
equal deleted inserted replaced
13206:650314ed845d 13212:5d0a30fad7de
1075 offset, date = timezone(string), string 1075 offset, date = timezone(string), string
1076 if offset != None: 1076 if offset != None:
1077 date = " ".join(string.split()[:-1]) 1077 date = " ".join(string.split()[:-1])
1078 1078
1079 # add missing elements from defaults 1079 # add missing elements from defaults
1080 for part in defaults: 1080 usenow = False # default to using biased defaults
1081 for part in ("S", "M", "HI", "d", "mb", "yY"): # decreasing specificity
1081 found = [True for p in part if ("%"+p) in format] 1082 found = [True for p in part if ("%"+p) in format]
1082 if not found: 1083 if not found:
1083 date += "@" + defaults[part] 1084 date += "@" + defaults[part][usenow]
1084 format += "@%" + part[0] 1085 format += "@%" + part[0]
1086 else:
1087 # We've found a specific time element, less specific time
1088 # elements are relative to today
1089 usenow = True
1085 1090
1086 timetuple = time.strptime(date, format) 1091 timetuple = time.strptime(date, format)
1087 localunixtime = int(calendar.timegm(timetuple)) 1092 localunixtime = int(calendar.timegm(timetuple))
1088 if offset is None: 1093 if offset is None:
1089 # local timezone 1094 # local timezone
1091 offset = unixtime - localunixtime 1096 offset = unixtime - localunixtime
1092 else: 1097 else:
1093 unixtime = localunixtime + offset 1098 unixtime = localunixtime + offset
1094 return unixtime, offset 1099 return unixtime, offset
1095 1100
1096 def parsedate(date, formats=None, defaults=None): 1101 def parsedate(date, formats=None, bias={}):
1097 """parse a localized date/time string and return a (unixtime, offset) tuple. 1102 """parse a localized date/time and return a (unixtime, offset) tuple.
1098 1103
1099 The date may be a "unixtime offset" string or in one of the specified 1104 The date may be a "unixtime offset" string or in one of the specified
1100 formats. If the date already is a (unixtime, offset) tuple, it is returned. 1105 formats. If the date already is a (unixtime, offset) tuple, it is returned.
1101 """ 1106 """
1102 if not date: 1107 if not date:
1108 date = date.strip() 1113 date = date.strip()
1109 try: 1114 try:
1110 when, offset = map(int, date.split(' ')) 1115 when, offset = map(int, date.split(' '))
1111 except ValueError: 1116 except ValueError:
1112 # fill out defaults 1117 # fill out defaults
1113 if not defaults:
1114 defaults = {}
1115 now = makedate() 1118 now = makedate()
1119 defaults = {}
1120 nowmap = {}
1116 for part in "d mb yY HI M S".split(): 1121 for part in "d mb yY HI M S".split():
1117 if part not in defaults: 1122 # this piece is for rounding the specific end of unknowns
1123 b = bias.get(part)
1124 if b is None:
1118 if part[0] in "HMS": 1125 if part[0] in "HMS":
1119 defaults[part] = "00" 1126 b = "00"
1120 else: 1127 else:
1121 defaults[part] = datestr(now, "%" + part[0]) 1128 b = "0"
1129
1130 # this piece is for matching the generic end to today's date
1131 n = datestr(now, "%" + part[0])
1132
1133 defaults[part] = (b, n)
1122 1134
1123 for format in formats: 1135 for format in formats:
1124 try: 1136 try:
1125 when, offset = strdate(date, format, defaults) 1137 when, offset = strdate(date, format, defaults)
1126 except (ValueError, OverflowError): 1138 except (ValueError, OverflowError):
1150 1162
1151 '<{date}' on or before a given date 1163 '<{date}' on or before a given date
1152 1164
1153 '>{date}' on or after a given date 1165 '>{date}' on or after a given date
1154 1166
1167 >>> p1 = parsedate("10:29:59")
1168 >>> p2 = parsedate("10:30:00")
1169 >>> p3 = parsedate("10:30:59")
1170 >>> p4 = parsedate("10:31:00")
1171 >>> p5 = parsedate("Sep 15 10:30:00 1999")
1172 >>> f = matchdate("10:30")
1173 >>> f(p1[0])
1174 False
1175 >>> f(p2[0])
1176 True
1177 >>> f(p3[0])
1178 True
1179 >>> f(p4[0])
1180 False
1181 >>> f(p5[0])
1182 False
1155 """ 1183 """
1156 1184
1157 def lower(date): 1185 def lower(date):
1158 d = dict(mb="1", d="1") 1186 d = dict(mb="1", d="1")
1159 return parsedate(date, extendeddateformats, d)[0] 1187 return parsedate(date, extendeddateformats, d)[0]