Beispiel #1
0
async def get_user_timeinfo(ctx, user, timepoint):
    from timezone_bot import query_zone
    user_timezone = await query_zone(user)

    if user_timezone == "Not set":
        await ctx.send(
            f"**You can set a time zone with `.tzlist` and then `.tzset`**")
        user_timezone = config["business"]["timezone"]

    zone_obj = ZoneInfo(user_timezone)
    # Here the placeholder is not limited to "-"
    user_timepoint = parse_time(timepoint, zone_obj=zone_obj)

    if user_timepoint:
        user_timepoint = user_timepoint.replace(tzinfo=zone_obj)
        std_zone_obj = ZoneInfo(config["business"]["timezone"])
        utc_timepoint = user_timepoint.astimezone(std_zone_obj)
        timepoint = get_closest_timepoint(utc_timepoint.replace(tzinfo=None), prefix=False)
    else:
        timepoint = get_closest_timepoint(get_earliest_timepoint(), prefix=False)

    display_timepoint = dateparser.parse(timepoint).replace(
        tzinfo=ZoneInfo(config["business"]["timezone"]))
    display_timepoint = display_timepoint.astimezone(zone_obj).strftime(os.getenv("datetime_format").split(".")[0])

    return "daily_" + timepoint, user_timezone, display_timepoint
Beispiel #2
0
def create_influxdb_dict(
    dev_id: str,
    measurement_name: str,
    fields: dict,
    tags: Optional[dict],
    timestamp: Optional[datetime.datetime],
    convert_floats: bool = False,
) -> dict:
    """
    Convert arguments to a valid InfluxDB measurement dict.

    :param dev_id: device id, mandatory tag for InfluxDB
    :param measurement_name:
    :param fields: dict containing metrics
    :param tags: dict containing additional tags
    :param timestamp: timezone aware datetime
    :param convert_floats: True if all values should be converted to floats
    :return: valid InfluxDB dict object
    """
    if timestamp is None:
        timestamp = datetime.datetime.now(ZoneInfo("UTC"))
    else:
        # Make sure datetime is timezone aware and in UTC time
        timestamp = timestamp.astimezone(ZoneInfo("UTC"))
    if tags is None:
        tags = {}
    if convert_floats:
        for k, v in fields.items():  # Convert all fields to floats
            fields[k] = float(v)
    # For historical reasons the main identifier (tag) is "dev-id"
    tags.update({"dev-id": dev_id})
    return {"measurement": measurement_name, "tags": tags, "fields": fields, "time": "{}".format(timestamp.isoformat())}
Beispiel #3
0
def get_timestamp(date: Optional[str] = None,
                  past: Optional[int] = 0,
                  future: Optional[int] = 0,
                  zone: Optional[str] = 'utc') -> str:
    """Get an ISO formatted timestamp.
    Args:
        date (str): An optional date to pin the timestamp to a specific time.
        past (int): Number of minutes in the past to get a timestamp.
        future (int): Number of minutes into the future to get a timestamp.
        zone (str): A specific timezone or US state abbreviation, e.g. CA.
    Returns:
        (str): An ISO formatted date/time string in the specified time zone,
            UTC by default.
    """
    time_zone = state_time_zones.get(str(zone).upper(), zone)
    if date:
        now = parser.parse(date).replace(tzinfo=ZoneInfo(time_zone))
    elif time_zone is None:
        now = datetime.now()
    else:
        now = datetime.now(ZoneInfo(time_zone))
    now += timedelta(minutes=future)
    now -= timedelta(minutes=past)
    if time_zone is None:
        return now.isoformat()[:19]
    else:
        return now.isoformat()
Beispiel #4
0
def get_iday_times(now) -> dict:

    # for datetime.combine, if date=datetime, its time components and tzinfo attributes ignored
    iday_times = {
        'nyc_close':
        datetime.combine(now - timedelta(days=1),
                         time(17, 0, 0, tzinfo=ZoneInfo('America/New_York'))),
        # 'asia_open': datetime.combine(now, time(8, 0, 0, tzinfo=ZoneInfo('Asia/Tokyo'))),
        'lndn_open':
        datetime.combine(now, time(8, 0, 0, tzinfo=ZoneInfo('Europe/London'))),
        'ldn_close':
        datetime.combine(now, time(16, 0, 0,
                                   tzinfo=ZoneInfo('Europe/London'))),
    }

    for ts in iday_times:
        if (iday_times[ts] - now).total_seconds(
        ) > -55 * 60:  # is within 55min or after, so shift day earlier
            iday_times[ts] -= timedelta(days=1)
        if iday_times[ts].weekday(
        ) >= 5:  # is Sat/Sun, so shift to prior Friday
            iday_times[ts] -= timedelta(days=iday_times[ts].weekday() -
                                        4)  # if Sat, weekday=5, Sun=6

    # sort by datetime
    # noinspection PyTypeChecker
    iday_times = dict(sorted(iday_times.items(), key=lambda item: item[1]))

    # ensure all times before now
    assert all((iday_times[dt] - now).total_seconds() < 0 for dt in iday_times)

    return iday_times
Beispiel #5
0
def proper_timezone():
    from datetime import datetime, timezone
    print(datetime.now(tz=timezone.utc))

    from zoneinfo import ZoneInfo
    print(ZoneInfo("America/Vancouver"))

    print(datetime.now(tz=ZoneInfo("Europe/Tallinn")))
    print(datetime.now(tz=ZoneInfo("Europe/Dublin")))
Beispiel #6
0
def normalize_timestamp(ts):
    # Convert to EST
    # Get into RFC3339 format
    dt_pst = datetime.strptime(
        ts,
        '%m/%d/%y %I:%M:%S %p').replace(tzinfo=ZoneInfo('America/Los_Angeles'))
    dt_est = dt_pst.astimezone(ZoneInfo('America/New_York'))

    return dt_est.isoformat()
def timezone_or_offset(from_):
    """
    Given ``from_`` creates `datetime.tzinfo` or `dateutil.tz.tzoffset` as
    result.

    ``from_`` can be any of following:

    - `str` (ie. "-02:42", None, "", "Z", ...) which is ISO8601 offset
    - `str` (ie. "Europe/Zagreb") which is timezone name
    - `int` (ie. -9000) which is total number of seconds in time offset
    - `datetime.timedelta`
    - `datetime.tzinfo` or something that behaves like it
    """
    offset_obj = None

    if from_ is None:
        offset_obj = ZoneInfo("UTC")

    elif isinstance(from_, str):
        try:
            offset_obj = ZoneInfo(from_)
        except (ZoneInfoNotFoundError, ValueError):
            pass

        if not offset_obj:
            if from_.strip() in ["Z", ""]:
                offset_obj = ZoneInfo("UTC")
            else:
                match_object = _ISO_8601_OFFSET.match(from_)
                if match_object:
                    sign, hours, minutes = match_object.groups()
                    offset_obj = tzoffset(
                        name=from_,
                        offset=timedelta(
                            hours=(-1 if sign == "-" else 1) * int(hours),
                            minutes=int(minutes or 0),
                        ),
                    )

    elif isinstance(from_, timedelta):
        offset_obj = tzoffset(name="{} s".format(from_.total_seconds()),
                              offset=from_)

    elif isinstance(from_, int):
        offset_obj = tzoffset(name="{} s".format(from_),
                              offset=timedelta(seconds=from_))

    elif issubclass(type(from_), tzinfo) or all(
            hasattr(from_, attr_name)
            for attr_name in ["dst", "fromutc", "tzname", "utcoffset"]):
        offset_obj = from_

    if offset_obj is None:
        raise ValueError("Unable to parse time offset: {}".format(from_))

    return offset_obj
Beispiel #8
0
    def test_zoneinfo(self):
        # On Python 3.9 ZoneInfo should be available.

        from zoneinfo import ZoneInfo

        info = ZoneInfo(key='America/Los_Angeles')
        dumped_info = jsons.dump(info)
        loaded_info = jsons.load(dumped_info, ZoneInfo)
        self.assertEqual(info, loaded_info)

        dt = datetime(2021, 8, 31, tzinfo=ZoneInfo("America/Los_Angeles"))
        dumped_dt = jsons.dump(dt)
        loaded_dt = jsons.load(dumped_dt, datetime)
        self.assertEqual(dt, loaded_dt)
Beispiel #9
0
def _time_domain_string(df, tzname):
    """Custom time label option."""
    sts = df["valid"].min().to_pydatetime()
    ets = df["valid"].max().to_pydatetime()
    timeformat = "%d %b %Y %I:%M %p"
    if tzname is not None:
        sts = sts.astimezone(ZoneInfo(tzname))
        ets = ets.astimezone(ZoneInfo(tzname))
    if tzname == "UTC":
        timeformat = "%d %b %Y %H:%M"
    return "%s - %s %s" % (
        sts.strftime(timeformat),
        ets.strftime(timeformat),
        "" if tzname is None else tzname,
    )
Beispiel #10
0
def test_rfc_1123_date() -> None:
    """
    The date is returned in the format described at
    https://library.vuforia.com/articles/Training/Using-the-VWS-API:

    ```
    Date: This is the current date per RFC 2616, section 3.3.1, rfc1123-date
    format, for example, Sun, 22 Apr 2012 08:49:37 GMT,

    NOTE: The date and time always refer to GMT.
    ```
    """
    not_gmt_timezone = ZoneInfo('America/New_York')
    frozen_time = datetime.datetime(
        year=2015,
        month=2,
        day=5,
        hour=9,
        minute=55,
        second=12,
        microsecond=11,
        tzinfo=not_gmt_timezone,
    )
    with freeze_time(frozen_time):
        result = vws_auth_tools.rfc_1123_date()

    assert result == 'Thu, 05 Feb 2015 14:55:12 GMT'
Beispiel #11
0
 def test_only_localtime(self):
     tz = tzlocal.unix._get_localzone(
         _root=os.path.join(self.path, 'test_data', 'localtime'))
     self.assertEqual(tz.key, 'local')
     dt = datetime(2012, 1, 1, 5)
     self.assertEqual(dt.replace(tzinfo=ZoneInfo('Africa/Harare')),
                      dt.replace(tzinfo=tz))
Beispiel #12
0
def test_data():
    """Test integrity of the data"""
    for key, airport in airports.items():
        assert key == airport['icao']
        assert airport['icao'].isupper() and len(airport['icao']) in (4, 3)
        assert airport['icao'].isalnum()
        assert isinstance(airport['name'], str)
        if airport['iata']:
            assert airport['iata'].isalpha() and airport['iata'].isupper(
            ) and len(airport['iata']) == 3
        assert isinstance(airport['name'], str)
        assert isinstance(airport['city'], str)
        assert isinstance(airport['subd'], str)
        assert isinstance(airport['country'], str)
        assert airport['country'] in iso_3166_1
        assert isinstance(airport['elevation'], float)
        assert isinstance(airport['lat'], float)
        assert isinstance(airport['lon'], float)
        assert ZoneInfo(airport['tz'])
        if airport['tz'] in tz_deprecated:
            warnings.warn(
                DeprecationWarning(
                    f'"{key}": tz "{airport["tz"]}" is deprecated; replace with correct one\n'
                    f'(see https://github.com/eggert/tz/blob/master/backward)')
            )
def test_destination_datetime_tzinfo_zoneinfo_nested():
    orig_tzname = time.tzname

    dest = LIBRARY_EPOCH_DATETIME.replace(
        tzinfo=ZoneInfo("Africa/Addis_Ababa"))
    with time_machine.travel(dest):
        assert time.tzname == ("EAT", "EAT")

        dest2 = LIBRARY_EPOCH_DATETIME.replace(
            tzinfo=ZoneInfo("Pacific/Auckland"))
        with time_machine.travel(dest2):
            assert time.tzname == ("NZST", "NZDT")

        assert time.tzname == ("EAT", "EAT")

    assert time.tzname == orig_tzname
def test_destination_datetime_tzinfo_zoneinfo():
    orig_timezone = time.timezone
    orig_altzone = time.altzone
    orig_tzname = time.tzname
    orig_daylight = time.daylight

    dest = LIBRARY_EPOCH_DATETIME.replace(
        tzinfo=ZoneInfo("Africa/Addis_Ababa"))
    with time_machine.travel(dest):
        assert time.timezone == -3 * 3600
        assert time.altzone == -3 * 3600
        assert time.tzname == ("EAT", "EAT")
        assert time.daylight == 0

        assert time.localtime() == time.struct_time((
            2020,
            4,
            29,
            0,
            0,
            0,
            2,
            120,
            0,
        ))

    assert time.timezone == orig_timezone
    assert time.altzone == orig_altzone
    assert time.tzname == orig_tzname
    assert time.daylight == orig_daylight
Beispiel #15
0
    def __init__(self):
        '''
            Initialize the backup task.

            >>> backup_task = BackupTask()
            >>> backup_task is not None
            True
            >>> backup_task.__init__()
            >>> type(backup_task.locale_tz)
            <class 'zoneinfo.ZoneInfo.Atlantic/Reykjavik'>
            >>> backup_task._interrupted
            False
            >>> backup_task.manager is None
            True
            >>> backup_task.log_name
            'blockchain_backup.bitcoin.backup.log'
        '''
        Thread.__init__(self)

        self._interrupted = False

        self.log = Log()
        self.log_name = os.path.basename(get_log_path())

        self.manager = None
        self.to_backup_dir = None
        self.backup_formatted_time = None

        self.locale_tz = ZoneInfo(TIME_ZONE)
Beispiel #16
0
 def _validate_timezone(self):
     if self._timezone is None:
         return
     try:
         self._timezone = ZoneInfo(self._timezone)
     except ZoneInfoNotFoundError:
         raise InvalidTimezone(f'{self._timezone} is not a valid timezone')
Beispiel #17
0
def get_input(
    year: int,
    day: int,
    input_path: Path,
) -> None:
    """
    Download input from AOC website

    Args:
        year       (int)         : The year of AOC
        day        (1..25)       : The day of AOC
        input_path (pathlib.Path): Path of file to write input to
    """
    if day not in range(1, 26):
        raise ValueError(f"{day=} is not in range 1..25")
    target_time_est = datetime(year,
                               12,
                               day - 1,
                               23,
                               59,
                               59,
                               500_000,
                               tzinfo=ZoneInfo("EST"))
    target_time_local = datetime.fromtimestamp(target_time_est.timestamp())
    while (now := datetime.now()) < target_time_local:
        diff = target_time_local - now
        seconds = diff.days * 86400 + diff.seconds
        print(f"{seconds} seconds until problem opens. Waiting...")
        sleep(max(diff.seconds - 1, 1))
Beispiel #18
0
    def get_grace_start(self, with_started=True):
        """ Return the datetime when the grace period starts.

        If the check is currently new, paused or down, return None.

        """

        # NEVER is a constant sentinel value (year 3000).
        # Using None instead would make the min() logic clunky.
        result = NEVER

        if self.kind == "simple" and self.status == "up":
            result = self.last_ping + self.timeout
        elif self.kind == "cron" and self.status == "up":
            # The complex case, next ping is expected based on cron schedule.
            # Don't convert to naive datetimes (and so avoid ambiguities around
            # DST transitions). cronsim will handle the timezone-aware datetimes.
            last_local = self.last_ping.astimezone(ZoneInfo(self.tz))
            result = next(CronSim(self.schedule, last_local))

        if with_started and self.last_start and self.status != "down":
            result = min(result, self.last_start)

        if result != NEVER:
            return result
Beispiel #19
0
def get_timezone_from_latlon(latitude: float, longitude: float) -> ZoneInfo:
    """
    Returns timezone ZoneInfo object
    """
    tz_str = tf.timezone_at(lng=longitude, lat=latitude)
    tz = datetime.timezone.utc if not tz_str else ZoneInfo(tz_str)
    return tz
def assert_valid_date_header(response: Response) -> None:
    """
    Assert that a response includes a `Date` header which is within two minutes
    of "now".

    Args:
        response: The response returned by a request to a Vuforia service.

    Raises:
        AssertionError: The response does not include a `Date` header which is
            within one minute of "now".
    """
    date_response = response.headers['Date']
    date_from_response = email.utils.parsedate(date_response)
    assert date_from_response is not None
    year, month, day, hour, minute, second, _, _, _ = date_from_response
    gmt = ZoneInfo('GMT')
    datetime_from_response = datetime.datetime(
        year=year,
        month=month,
        day=day,
        hour=hour,
        minute=minute,
        second=second,
        tzinfo=gmt,
    )
    current_date = datetime.datetime.now(tz=gmt)
    time_difference = abs(current_date - datetime_from_response)
    assert time_difference < datetime.timedelta(minutes=2)
    def update_config(self, config):
        """Update config entries."""
        self._name = config.get(CONF_NAME)
        self.url = config.get(CONF_URL)
        # Early versions did not have these variables, as such it may not be
        # set, this should guard against issues until we're certain
        # we can remove this guard.
        try:
            self.timezone = ZoneInfo(config.get(CONF_TIMEZONE))
        except TypeError:
            self.timezone = dt.DEFAULT_TIME_ZONE
        self.refresh_frequency = config.get(CONF_REFRESH_FREQUENCY)
        if self.refresh_frequency is None:
            self.refresh_frequency = DEFAULT_REFRESH_FREQUENCY
        # always do a refresh ASAP after a config change
        self.next_refresh = dt.now()
        self.event_prefix = config.get(CONF_EVENT_PREFIX)
        # our config flow guarantees that checkin and checkout are valid times
        # just use cv.time to get the parsed time object
        self.checkin = cv.time(config.get(CONF_CHECKIN))
        self.checkout = cv.time(config.get(CONF_CHECKOUT))
        self.max_events = config.get(CONF_MAX_EVENTS)
        self.days = config.get(CONF_DAYS)
        self.code_generator = config.get(CONF_CODE_GENERATION, DEFAULT_CODE_GENERATION)
        # Early versions did not have this variable, as such it may not be
        # set, this should guard against issues until we're certain
        # we can remove this guard.
        try:
            self.ignore_non_reserved = config.get(CONF_IGNORE_NON_RESERVED)
        except NameError:
            self.ignore_non_reserved = None
        self.verify_ssl = config.get(CONF_VERIFY_SSL)

        # updated the calendar in case the fetch days has changed
        self.calendar = self._refresh_event_dict()
 def default_zone_info_deserializer(obj: ZoneInfo, *_, **__) -> ZoneInfo:
     """
     Deserialize a ZoneInfo.
     :param obj: a serialized ZoneInfo object.
     :return: an instance of ZoneInfo.
     """
     return ZoneInfo(obj['key'])
Beispiel #23
0
def get_timerange(date):
    """Figure out what period to get data for."""
    # Construct a CDT/CST Midnight to 11 PM period
    ts = datetime.datetime(
        date.year, date.month, date.day, 0, tzinfo=ZoneInfo("America/Chicago")
    )
    return ts, ts.replace(hour=23)
    def from_json(cls, json_object: dict[str, Any]) -> PGNInfo:
        json_object['start_date'] = datetime.fromtimestamp(json_object.pop('startDate')).astimezone(tz=timezone.utc)
        json_object['time_control'] = int(json_object.pop('timeControl'))
        json_object['move_timestamps'] = tuple(
            int(move_timestamp)
            for move_timestamp in json_object.pop('moveTimestamps').split(',')
        )

        json_object['end_time']: datetime = datetime.strptime(
            json_object.pop('endTime').split()[0],
            '%H:%M:%S'
        ).replace(
            year=json_object['start_date'].year,
            month=json_object['start_date'].month,
            day=json_object['start_date'].day,
            tzinfo=ZoneInfo('America/Los_Angeles')
        ).astimezone(tz=timezone.utc)

        if json_object['end_time'] < json_object['start_date']:
            latest_end_datetime: datetime = json_object['start_date'] + timedelta(seconds=json_object['time_control'])

            json_object['end_time'].replace(
                year=latest_end_datetime.year,
                month=latest_end_datetime.month,
                day=latest_end_datetime.day,

            )

        return super().from_json(json_object=json_object)
Beispiel #25
0
 def read_tip(self, tip_id):
     assert self._login_service.is_authenticated()
     tip = self._readingtip_repository.get_tip(tip_id)
     assert tip.user == self._login_service.current_user()
     assert not tip.read, "Tip already marked as read"
     date = datetime.now(ZoneInfo("Europe/Helsinki")).strftime("%d/%m/%Y, %H:%M")
     self._readingtip_repository.read_tip(tip, date)
Beispiel #26
0
    def map_program_play(self, prog_info):
        """This is the implementation for MPR

        raw data in: [tuple] (pl_date, bs4 'dt' tag)
        normalized data out: {
            'program': {},
            'program_play': {}
        }
        """
        pl_date, prog_head = prog_info
        prog_name = prog_head.h2.string.strip()
        m = re.match(r'(\d+:\d+ (?:AM|PM)).+?(\d+:\d+ (?:AM|PM))', prog_name)
        start_time = dt.datetime.strptime(m.group(1), '%I:%M %p').time()
        end_time = dt.datetime.strptime(m.group(2), '%I:%M %p').time()
        start_date = pl_date
        end_date = pl_date if end_time > start_time else pl_date + dt.timedelta(
            1)
        tz = ZoneInfo(self.station.timezone)
        # TODO: lookup host name from refdata!!!
        prog_data = {'name': prog_name}

        pp_data = {}
        # TODO: convert prog_head into dict for prog_play_info!!!
        pp_data['prog_play_info'] = {}
        pp_data['prog_play_date'] = start_date
        pp_data['prog_play_start'] = start_time
        pp_data['prog_play_end'] = end_time
        pp_data['prog_play_dur'] = None  # Interval, if listed
        pp_data['notes'] = None  # ARRAY(Text)
        pp_data['start_time'] = datetimetz(start_date, start_time, tz)
        pp_data['end_time'] = datetimetz(end_date, end_time, tz)
        pp_data['duration'] = pp_data['end_time'] - pp_data['start_time']

        return {'program': prog_data, 'program_play': pp_data}
Beispiel #27
0
def make(parsed, monday):
    calendar = Calendar()
    calendar.creator = "eAUrnik - Fork me on GitHub: https://git.io/JO5Za"
    
    durations = []
    for duration in parsed[0]:
        start, end = duration.split(" - ")
        start_hours, start_minutes = map(int, start.split(":"))
        end_hours, end_minutes = map(int, end.split(":"))
        durations.append(((start_hours, start_minutes), (end_hours, end_minutes)))
        
    data = parsed[1]
    for day_index in range(0, len(data)):
        day = monday + timedelta(days = day_index)
        lessons = data[day_index]
        for lesson_index in range(0, len(lessons)):
            for lesson in lessons[lesson_index]:
                title = lesson[0]
                subtitle = lesson[1]
                
                duration = durations[lesson_index]
                timezone = ZoneInfo("Europe/Ljubljana")
                start = datetime(day.year, day.month, day.day, duration[0][0], duration[0][1], tzinfo = timezone)
                end = datetime(day.year, day.month, day.day, duration[1][0], duration[1][1], tzinfo = timezone)

                event = Event()
                event.name = title
                event.location = subtitle
                event.begin = start
                event.end = end
                calendar.events.add(event)

    return string(calendar)
Beispiel #28
0
def create_influxdb_line(
    dev_id: str, measurement_name: str, fields: dict, tags: Optional[dict], timestamp: Optional[datetime.datetime]
) -> str:
    """
    Convert arguments to a valid InfluxDB line protocol string.

    :param dev_id: device id, mandatory tag for InfluxDB
    :param measurement_name:
    :param fields: dict containing metrics
    :param timestamp: timezone aware datetime
    :param tags: dict containing additional tags
    :return: valid InfluxDB line protocol string
    """
    if timestamp is None:
        time_int = int(time.time() * 10**9)
    else:
        # Make sure datetime is timezone aware and in UTC time
        timestamp = timestamp.astimezone(ZoneInfo("UTC"))
        time_int = int(timestamp.timestamp() * 10**9)  # epoch in nanoseconds
    if tags is None:
        tags = {}
    # For historical reasons the main identifier (tag) is "dev-id"
    tags.update({"dev-id": dev_id})
    # Convert dict to sorted comma separated list of key=val pairs, e.g. tagA=foo,tagB=bar
    tag_str = ",".join([f"{i[0]}={i[1]}" for i in sorted(list(tags.items()))])
    for k, v in fields.items():
        fields[k] = float(v)
    field_str = ",".join([f"{i[0]}={i[1]}" for i in sorted(list(fields.items()))])
    # measurement,tag1=val1 field1=3.8234,field2=4.23874 1610089552385868032
    measurement = f"{measurement_name},{tag_str} {field_str} {time_int}"
    return measurement
Beispiel #29
0
    def __getattr__(self, field: str) -> Any:
        field_data = self.data.get(field)
        if isinstance(field_data, dict):
            return Result(field, {field: field_data})
        if isinstance(field_data, list):
            return ListResult(field, field, {field: field_data}, include_pages=False)
        if isinstance(field_data, str):
            # Check if the String is a date
            try:
                return date.fromisoformat(field_data)  # type: ignore
            except ValueError:
                pass

            # Check if the String is a datetime
            try:
                # This logic pains me, but datetimes in FreshBooks:
                # - Project-like resources return dates in UTC.
                #   Most use proper ISO 8601 format, but many omit the UTC time zone
                #   designator ("Z") at the end (but are still UTC). Python `fromisoformat`
                #   doesn't like the "Z", so we strip it.
                # - Accounting resources return dates in "US/Eastern",
                #   except the client signup date, and a few new API endpoints, which are UTC.
                #   These dates are in the format "yyyy-MM-dd HH:mm:ss",
                #   so we can distinguish them with the absent "T".
                parsed_date = datetime.fromisoformat(field_data.rstrip("Z"))  # type: ignore
                if "T" in field_data or _is_accounting_utc_date_field(self._name, field):
                    return parsed_date.replace(tzinfo=timezone.utc)
                return parsed_date.replace(tzinfo=ZoneInfo("US/Eastern")).astimezone(timezone.utc)
            except ValueError:
                return field_data

        return field_data
Beispiel #30
0
async def plat0(msg: Message) -> None:
    word = random.choice(["basta", "senti", "smettila"])
    text = f"oh {word} non mi spoilerare"
    timestamp = datetime.now(ZoneInfo("Europe/Rome"))
    if 3 <= timestamp.hour <= 5:
        text += ", che mi sono appena svegliato"
    await msg.reply(text)