Source code for badidatetime._structures

# -*- coding: utf-8 -*-
#
# badidatetime/_structures.py
#
__docformat__ = "restructuredtext en"

import importlib
from typing import NamedTuple


[docs] class ShortFormStruct(NamedTuple): """ Implements a short form Badí' date and time NamedTuple. """ tm_year: int # range[-1842, 1161] tm_mon: int # range[0, 19] tm_mday: int # range[1, 19] tm_hour: int # range[0, 23] tm_min: int # range[0, 59] tm_sec: float # range[0, 61] tm_wday: int # range[0, 6]; Jalál (Saturday) is 0 tm_yday: int # range[1, 366]; day in year # tm_isdst, may be set to 1 when daylight savings time is in effect, # and 0 when it is not. A value of -1 indicates that this is not known, # and will usually result in the correct state being filled in. tm_isdst: int # 0, 1 or -1 (set only with localtime) # abbreviation of timezone name (set only with localtime) tm_zone: str = None # offset east of UTC in seconds (set only with localtime) tm_gmtoff: int = None @property def short(self): """ Indicates if this NamedTuple is a short or long form Badí' date. """ return True def __repr__(self) -> str: return (f"structures.ShortFormStruct(tm_year={self.tm_year}, " f"tm_mon={self.tm_mon}, tm_mday={self.tm_mday}, " f"tm_hour={self.tm_hour}, tm_min={self.tm_min}, " f"tm_sec={self.tm_sec}, tm_wday={self.tm_wday}, " f"tm_yday={self.tm_yday}, tm_isdst={self.tm_isdst})")
[docs] class LongFormStruct(NamedTuple): """ Implements a long form Badí' date and time NamedTuple. """ tm_kull_i_shay: int # example, 1 tm_vahid: int # range[1, 19] tm_year: int # range[1, 19] tm_mon: int # range[0, 19] tm_mday: int # range[1, 19] tm_hour: int # range[0, 23] tm_min: int # range[0, 59] tm_sec: float # range[0, 61] tm_wday: int # range[0, 6]; Jalál (Saturday) is 0 tm_yday: int # range[1, 366]; day in year # tm_isdst, may be set to 1 when daylight savings time is in effect, # and 0 when it is not. A value of -1 indicates that this is not known, # and will usually result in the correct state being filled in. tm_isdst: int # 0, 1 or -1 (set only with localtime) # abbreviation of timezone name (set only with localtime) tm_zone: str = None # offset east of UTC in seconds (set only with localtime) tm_gmtoff: int = None @property def short(self): """ Indicates if this NamedTuple is a short or long form Badí' date. """ return False def __repr__(self) -> str: return (f"structures.LongFormStruct(" f"tm_kull_i_shay={self.tm_kull_i_shay}, " f"tm_vahid={self.tm_vahid}, tm_year={self.tm_year}, " f"tm_mon={self.tm_mon}, tm_mday={self.tm_mday}, " f"tm_hour={self.tm_hour}, tm_min={self.tm_min}, " f"tm_sec={self.tm_sec}, tm_wday={self.tm_wday}, " f"tm_yday={self.tm_yday}, tm_isdst={self.tm_isdst})")
[docs] class struct_time: """ Create a structure representing a Badí' date and time. """ def __new__(cls, date: tuple, tzinfo=None): """ Creates a ShortFormStruct or LongFormStruct NamedTuple. :param tuple date: A tuple containing the data needed to create a NamedTuple. :param tzinfo tzinfo: Timezone information or None. :returns: Instance object :rtype: ShortFormStruct or LongFormStruct """ self = object.__new__(cls) super().__init__(self) short = cls.__is_short_form(date) if date[-1] not in (-1, 0, 1): msg = (f"Invalid isdst '{date[-1]}', it must be in the range " "of [-1, 1].") raise ValueError(msg) if short: inst = ShortFormStruct( *self.__fill_in_missing(date, tzinfo, short)) else: inst = LongFormStruct( *self.__fill_in_missing(date, tzinfo, short)) return inst @classmethod def __is_short_form(cls, date: tuple): """ Determines if the date tuple contains short or long form data. :param tuple date: The date tuple to be processed. :returns: If `True` then the date tuple represents a short form Badí' date and time, if `False` date tuple represents a long form Badí' date and time. :rtype: bool :raises TypeError: Wrong tuple sequence size. """ d_size = len(date) if d_size == 9: short = True elif d_size == 11: short = False else: raise TypeError("struct_time() takes a 9 or 11-sequence " f"({d_size}-sequence given)") return short @classmethod def __fill_in_missing(cls, date: tuple, tzinfo, short: bool): """ Fill in missing data. :param tuple date: The date tuple to be processed. :param tzinfo tzinfo: Timezone information or None. :param bool short: If `True` then the date tuple represents a short form Badí' date and time, if `False` date tuple represents a long form Badí' date and time. :returns: The updated date tuple. :rtype: tuple """ datetime = importlib.import_module('badidatetime.datetime') if short: b_date = date[:3] + (None, None) + date[3:6] else: b_date = date[:8] date = list(date) dt = datetime.datetime(*b_date, tzinfo=tzinfo) # Build out the tm_isdst, tm_zone and tm_gmtoff. if tzinfo: dst = tzinfo.dst(dt) if hasattr(dst, 'total_seconds'): ts = dst.total_seconds() if ts: date[-1] = 1 elif ts == 0: date[-1] = 0 offset = dt.utcoffset() total_seconds = offset.total_seconds() if offset else None if tzinfo and hasattr(tzinfo, 'tzname'): tm_zone = tzinfo.tzname(dt) else: tm_zone = dt.tzname() date += [tm_zone, total_seconds] return tuple(date)