__init__.py (11522B)
1 #Embedded file name: C:\BuildAgent\work\20d73f1b24eed06e\eve\release\V24.01\packages\datetimeutils\__init__.py 2 import datetime 3 import re 4 import time 5 __version__ = (2, 3, 0, 0) 6 from datetimeutils.monolithext import * 7 from datetimeutils.parsers.timedelta import str_to_timedelta 8 _string_types = tuple({type(u''), type('')}) 9 _number_types = tuple({type(0), type(18446744073709551615L)}) 10 _NOT_SUPPLIED = object() 11 FILETIME_NULL_DATE = datetime.datetime(1601, 1, 1, 0, 0, 0) 12 ISODATE_REGEX = re.compile('^(?:(?P<year>[0]{0,3}[1-9]\\d{0,3})[- /.,\\\\](?P<month>1[012]|0?\\d)[- /.,\\\\](?P<day>3[01]|[012]?\\d))?(?:[ @Tt]{0,1}(?:(?P<hour>[2][0-3]|[01]?\\d)[ .:,](?P<minute>[012345]?\\d))?(?:[ .:,](?P<second>[012345]?\\d)(?:[ .:,](?P<millisecond>\\d{0,6}))?)?)?') 13 DATE_REXEX = re.compile('(?P<year>[0]{0,3}[1-9]\\d{0,3})[- /.,\\\\](?P<month>1[012]|0?\\d)[- /.,\\\\](?P<day>3[01]|[012]?\\d)') 14 REVERSE_DATETIME_REXEX = re.compile('(?P<day>3[01]|[012]?\\d)[- /.,\\\\](?P<month>1[012]|0?\\d)[- /.,\\\\](?P<year>[12][0189]\\d{2})(?:[ @Tt]{0,1}(?:(?P<hour>[2][0-3]|[01]?\\d)[ .:,](?P<minute>[012345]?\\d))?(?:[ .:,](?P<second>[012345]?\\d)(?:[ .:,](?P<millisecond>\\d{0,6}))?)?)?') 15 REVERSE_US_DATETIME_REXEX = re.compile('(?P<month>1[012]|0?\\d)[- /.,\\\\](?P<day>3[01]|[012]?\\d)[- /.,\\\\](?P<year>[12][0189]\\d{2})(?:[ @Tt]{0,1}(?:(?P<hour>[2][0-3]|[01]?\\d)[ .:,](?P<minute>[012345]?\\d))?(?:[ .:,](?P<second>[012345]?\\d)(?:[ .:,](?P<millisecond>\\d{0,6}))?)?)?') 16 MEAN_MONTH = 30.436875 17 MEAN_YEAR = 365.2425 18 FILETIME_UNIXTIME_DIFF = 11644473600L 19 FILETIME_SEC_TICKS = 10000000 20 21 def filetime_to_datetime(filetime): 22 return FILETIME_NULL_DATE + datetime.timedelta(microseconds=filetime / 10) 23 24 25 def datetime_to_filetime(dt): 26 if not isinstance(dt, datetime.datetime) and isinstance(dt, datetime.date): 27 dt = datetime.datetime.combine(dt, datetime.time(0, 0, 0)) 28 delta = dt - FILETIME_NULL_DATE 29 return timedelta_to_filetime(delta) 30 31 32 def timedelta_to_filetime(delta): 33 return 10 * ((delta.days * 86400 + delta.seconds) * 1000000 + delta.microseconds) 34 35 36 def datetime_to_timestamp(dt): 37 if not isinstance(dt, datetime.datetime) and isinstance(dt, datetime.date): 38 dt = datetime.datetime.combine(dt, datetime.time(0, 0, 0)) 39 return int(time.mktime(dt.timetuple())) 40 41 42 def regex_to_datetime(string, regex_pattern): 43 match = regex_pattern.match(string.strip()) 44 if match: 45 parts = match.groupdict() 46 found_date = False 47 if parts['year'] and parts['month'] and parts['day']: 48 date_part = datetime.date(int(parts['year']), int(parts['month']), int(parts['day'])) 49 found_date = True 50 else: 51 date_part = datetime.date.today() 52 found_time = False 53 if parts['hour'] and parts['minute']: 54 time_part = datetime.time(int(parts['hour']), int(parts['minute']), int(parts['second'] or 0), int(parts['millisecond'] or 0)) 55 found_time = True 56 else: 57 time_part = datetime.time() 58 if found_date or found_time: 59 return datetime.datetime.combine(date_part, time_part) 60 61 62 def isostr_to_datetime(string): 63 match = ISODATE_REGEX.match(string.strip()) 64 if match: 65 parts = match.groupdict() 66 found_date = False 67 if parts['year'] and parts['month'] and parts['day']: 68 date_part = datetime.date(int(parts['year']), int(parts['month']), int(parts['day'])) 69 found_date = True 70 else: 71 date_part = datetime.date.today() 72 found_time = False 73 if parts['hour'] and parts['minute']: 74 time_part = datetime.time(int(parts['hour']), int(parts['minute']), int(parts['second'] or 0), int(parts['millisecond'] or 0)) 75 found_time = True 76 else: 77 time_part = datetime.time() 78 if found_date or found_time: 79 return datetime.datetime.combine(date_part, time_part) 80 81 82 def any_to_datetime(temporal_object, default = _NOT_SUPPLIED, utc = True): 83 if default == _NOT_SUPPLIED: 84 default = temporal_object 85 try: 86 if isinstance(temporal_object, datetime.datetime): 87 return temporal_object 88 if isinstance(temporal_object, datetime.date): 89 return datetime.datetime.combine(temporal_object, datetime.time()) 90 if isinstance(temporal_object, float): 91 if temporal_object > 29999999999L: 92 temporal_object = int(temporal_object) 93 elif utc: 94 return datetime.datetime.utcfromtimestamp(temporal_object) 95 else: 96 return datetime.datetime.fromtimestamp(temporal_object) 97 98 if isinstance(temporal_object, _number_types): 99 if temporal_object > 29999999999L: 100 return filetime_to_datetime(temporal_object) 101 elif utc: 102 return datetime.datetime.utcfromtimestamp(temporal_object) 103 else: 104 return datetime.datetime.fromtimestamp(temporal_object) 105 if isinstance(temporal_object, _string_types): 106 value = regex_to_datetime(temporal_object, REVERSE_DATETIME_REXEX) 107 if value: 108 return value 109 value = regex_to_datetime(temporal_object, REVERSE_US_DATETIME_REXEX) 110 if value: 111 return value 112 value = isostr_to_datetime(temporal_object) 113 if value: 114 return value 115 except (OverflowError, ValueError): 116 pass 117 118 return default 119 120 121 def _div_and_rest(total, chunk): 122 divs = int(total / chunk) 123 return (divs, total - chunk * divs) 124 125 126 def split_delta(delta, include_weeks = True, include_months = True, include_years = True): 127 parts = {'1st': None, 128 '2nd': None, 129 'is_past': False} 130 if delta.total_seconds() < 0: 131 parts['is_past'] = True 132 delta = datetime.timedelta(seconds=-delta.total_seconds()) 133 days = abs(delta.days) 134 if include_years: 135 parts['years'], days = _div_and_rest(days, MEAN_YEAR) 136 if parts['years']: 137 parts['1st'] = 'years' 138 if include_months: 139 parts['months'], days = _div_and_rest(days, MEAN_MONTH) 140 if parts['months']: 141 if not parts['1st']: 142 parts['1st'] = 'months' 143 else: 144 parts['2nd'] = 'months' 145 if include_weeks: 146 parts['weeks'], days = _div_and_rest(days, 7) 147 if not parts['1st'] and parts['weeks']: 148 parts['1st'] = 'weeks' 149 elif not parts['2nd'] and parts['weeks']: 150 parts['2nd'] = 'weeks' 151 parts['days'] = int(days) 152 if not parts['1st'] and parts['days']: 153 parts['1st'] = 'days' 154 elif not parts['2nd'] and parts['days']: 155 parts['2nd'] = 'days' 156 seconds = abs(delta.seconds) 157 parts['hours'], seconds = _div_and_rest(seconds, 3600) 158 if not parts['1st'] and parts['hours']: 159 parts['1st'] = 'hours' 160 elif not parts['2nd'] and parts['hours']: 161 parts['2nd'] = 'hours' 162 parts['minutes'], seconds = _div_and_rest(seconds, 60) 163 if not parts['1st'] and parts['minutes']: 164 parts['1st'] = 'minutes' 165 elif not parts['2nd'] and parts['minutes']: 166 parts['2nd'] = 'minutes' 167 parts['seconds'] = int(seconds) 168 if not parts['1st'] and parts['seconds']: 169 parts['1st'] = 'seconds' 170 elif not parts['2nd'] and parts['seconds']: 171 parts['2nd'] = 'seconds' 172 return parts 173 174 175 def deltastr(delta, default = ''): 176 if not isinstance(delta, datetime.timedelta): 177 return default 178 parts = split_delta(delta) 179 if parts['1st']: 180 first_key = parts['1st'] 181 if first_key == 'seconds': 182 return 'a few seconds' 183 first_value = parts[first_key] 184 if first_value > 1: 185 return '%s %s' % (first_value, first_key) 186 first_key = first_key[:-1] 187 if parts['2nd'] and parts['2nd'] != 'seconds': 188 second_key = parts['2nd'] 189 second_value = parts[second_key] 190 if second_value < 2: 191 second_key = second_key[:-1] 192 return '%s %s and %s %s' % (first_value, 193 first_key, 194 second_value, 195 second_key) 196 else: 197 return '%s %s' % (first_value, first_key) 198 else: 199 return 'a few seconds' 200 201 202 def ago(delta_or_date, default = '', utc = True): 203 if utc: 204 now = datetime.datetime.utcnow() 205 else: 206 now = datetime.datetime.now() 207 if isinstance(delta_or_date, datetime.datetime): 208 delta_or_date = now - delta_or_date 209 elif isinstance(delta_or_date, datetime.date): 210 delta_or_date = now.date() - delta_or_date 211 elif isinstance(delta_or_date, datetime.time): 212 delta_or_date = datetime.datetime.combine(now.date(), delta_or_date) 213 return deltastr(delta_or_date, default) 214 215 216 def find_earliest_time_after_datetime(dt, time): 217 dt_with_time_replaced = datetime.datetime.combine(dt.date(), time) 218 if dt_with_time_replaced <= dt: 219 dt_with_time_replaced += datetime.timedelta(days=1) 220 return dt_with_time_replaced 221 222 223 def find_earliest_time_and_weekday_after_datetime(dt, time_of_day, day_of_week): 224 dt_with_time_replaced = datetime.datetime.combine(dt.date(), time_of_day) 225 if dt_with_time_replaced <= dt: 226 dt_with_time_replaced += datetime.timedelta(days=1) 227 days_to_advance = (day_of_week - dt_with_time_replaced.weekday()) % 7 228 return dt_with_time_replaced + datetime.timedelta(days=days_to_advance) 229 230 231 def dt_midnight(dt): 232 if isinstance(dt, datetime.datetime): 233 dt = dt.date() 234 if isinstance(dt, datetime.date): 235 return datetime.datetime.combine(dt, datetime.time()) 236 return dt 237 238 239 def dt_from_now(days = 0, hours = 0, minutes = 0, seconds = 0, weeks = 0): 240 return datetime.datetime.now() + datetime.timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds, weeks=weeks) 241 242 243 def dt_ago(days = 0, hours = 0, minutes = 0, seconds = 0, weeks = 0): 244 return datetime.datetime.now() - datetime.timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds, weeks=weeks) 245 246 247 def date_from_now(days = 0, weeks = 0): 248 return dt_midnight(dt_from_now(days, weeks)) 249 250 251 def date_ago(days = 0, weeks = 0): 252 return dt_midnight(dt_ago(days, weeks)) 253 254 255 def str_to_relative_datetime(str_value): 256 str_value = str_value.strip().lower() 257 if str_value in ('now', 'today'): 258 return datetime.datetime.now() 259 elif str_value == 'yesterday': 260 return datetime.datetime.now() - datetime.timedelta(days=1) 261 elif str_value == 'tomorrow': 262 return datetime.datetime.now() + datetime.timedelta(days=1) 263 else: 264 return None 265 266 267 def str_to_2dates(str_value): 268 try: 269 match = DATE_REXEX.findall(str_value.strip()) 270 if match: 271 if len(match) == 2: 272 if len(match[0]) == 3 and len(match[1]) == 3: 273 date_from = datetime.date(int(match[0][0]), int(match[0][1]), int(match[0][2])) 274 date_to = datetime.date(int(match[1][0]), int(match[1][1]), int(match[1][2])) 275 return (date_from, date_to) 276 return None 277 except Exception: 278 return None 279 280 281 def serialize(temporal_object): 282 if isinstance(temporal_object, (datetime.datetime, datetime.date, datetime.time)): 283 return temporal_object.isoformat() 284 elif isinstance(temporal_object, datetime.timedelta): 285 return temporal_object.total_seconds() 286 else: 287 return temporal_object 288 289 290 def to_str(temporal_object): 291 return str(serialize(temporal_object))