def _timezone_struct(name): # this is a bit painful. we need to generate a MAPI timezone structure # (rule) from an 'olson' name. on the one hand the olson db (as in pytz) # does not expose the actual DST rules, if any, and just expands all # transitions. this means we have to do some guess work. # on the other hand, the MAPI struct/rule is quite limited (transition # always on "Nth weekday in month", and not historical). ideally of course # we move away from the MAPI struct altogether, and just use the olson name.. # but that would probably break other clients at this point. tz = pytz.timezone(name) now = datetime.datetime.now() year = now.year yearstart = datetime.datetime(year, 1, 1) runningdst = tz.dst(yearstart) UTCBIAS = tz.utcoffset(yearstart) DSTBIAS = None DSTSTART = None DSTEND = None ZERO = datetime.timedelta(0) days = 366 if calendar.isleap(year) else 365 for day in range(days): # TODO find matching transitions dt = datetime.datetime(year, 1, 1) + datetime.timedelta(days=day) datedst = tz.dst(dt) if runningdst == ZERO and datedst != ZERO: runningdst = datedst UTCBIAS = tz.utcoffset(dt) - datedst DSTBIAS = datedst DSTSTART = dt elif runningdst != ZERO and datedst == ZERO: runningdst = datedst DSTEND = dt utcbias = -UTCBIAS.seconds // 60 if DSTBIAS: dstbias = -DSTBIAS.seconds // 60 startmonth = DSTSTART.month endmonth = DSTEND.month weekday = DSTSTART.weekday( ) # TODO don't assume start/end are same weekday and last-in-month return struct.pack(TZFMT, utcbias, 0, dstbias, 0, 0, endmonth, weekday, 5, 0, 0, 0, 0, 0, 0, startmonth, weekday, 5, 0, 0, 0, 0) else: return struct.pack(TZFMT, utcbias, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0)
def get_date(schedule=False, rule=None, last_date=None, tz=None, iso8601=False): """Returns a date stamp, given a recurrence rule. schedule - bool: whether to use the recurrence rule or not rule - str: an iCal RRULE string that specifies the rule for scheduling posts last_date - datetime: timestamp of the last post tz - tzinfo: the timezone used for getting the current time. iso8601 - bool: whether to force ISO 8601 dates (instead of locale-specific ones) """ if tz is None: tz = dateutil.tz.tzlocal() date = now = datetime.datetime.now(tz) if schedule: try: from dateutil import rrule except ImportError: LOGGER.error('To use the --schedule switch of new_post, ' 'you have to install the "dateutil" package.') rrule = None # NOQA if schedule and rrule and rule: try: rule_ = rrule.rrulestr(rule, dtstart=last_date) except Exception: LOGGER.error('Unable to parse rule string, using current time.') else: date = rule_.after(max(now, last_date or now), last_date is None) offset = tz.utcoffset(now) offset_sec = (offset.days * 24 * 3600 + offset.seconds) offset_hrs = offset_sec // 3600 offset_min = offset_sec % 3600 if iso8601: tz_str = '{0:+03d}:{1:02d}'.format(offset_hrs, offset_min // 60) return date.strftime('%Y-%m-%dT%T') + tz_str else: if offset: tz_str = ' UTC{0:+03d}:{1:02d}'.format(offset_hrs, offset_min // 60) else: tz_str = ' UTC' return date.strftime('{0} {1}'.format( locale.nl_langinfo(locale.D_FMT), locale.nl_langinfo(locale.T_FMT), )) + tz_str
def _getNikolaTime(self, ctime): time = datetime.fromtimestamp(ctime) tz = dateutil.tz.tzlocal() offset = tz.utcoffset(time) offset_sec = (offset.days * 24 * 3600 + offset.seconds) offset_hrs = offset_sec // 3600 offset_min = offset_sec % 3600 tz_str = '{0:+03d}:{1:02d}'.format(offset_hrs, offset_min // 60) if offset: tz_str = ' UTC{0:+03d}:{1:02d}'.format(offset_hrs, offset_min // 60) else: tz_str = ' UTC' return time.strftime('%Y-%m-%d %H:%M:%S') + tz_str
def testOffset(self): tz = tzwin.tzwin("Cape Verde Standard Time") self.assertEqual(tz.utcoffset(datetime(1995, 5, 21, 12, 9, 13)), timedelta(-1, 82800))