cardinal_pythonlib.datetimefunc
Original code copyright (C) 2009-2022 Rudolf Cardinal (rudolf@pobox.com).
This file is part of cardinal_pythonlib.
Licensed under the Apache License, Version 2.0 (the “License”); you may not use this file except in compliance with the License. You may obtain a copy of the License at
Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an “AS IS” BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.
Support functions for date/time.
Note regarding durations:
datetime.timedeltatakes parameters from microseconds to weeks; these are all exact.isodate.isoduration.Durationalso includes years and months, which are well defined but not constant. It is explicit that it has two basic components: {year, month} and {timedelta}. Internally, it also treats years and months as separate.pendulum.Durationhas the same span from microseconds to years, but it has internal assumptions (in v2.1.1+ at least) that a year is 365 days and a month is 30 days.
- cardinal_pythonlib.datetimefunc.coerce_to_date(x: Any, assume_local: bool = False, to_utc: bool = False) date | None[source]
Ensure an object is a
datetime.date, or coerce to one, or raiseValueErrororOverflowError(as per https://dateutil.readthedocs.org/en/latest/parser.html).See also
coerce_to_pendulum_date(), noting thatpendulum.Dateis a subclass ofdatetime.date.
- cardinal_pythonlib.datetimefunc.coerce_to_datetime(x: Any) datetime | None[source]
Ensure an object is a
datetime.datetime, or coerce to one, or raiseValueErrororOverflowError(as per https://dateutil.readthedocs.org/en/latest/parser.html).
- cardinal_pythonlib.datetimefunc.coerce_to_pendulum(x: None | datetime | date | DateTime | str | Arrow, assume_local: bool = False) DateTime | None[source]
Converts something to a
pendulum.DateTime.- Parameters:
- Returns:
a
pendulum.DateTime, orNone.- Raises:
pendulum.parsing.exceptions.ParserError – if a string fails to parse
ValueError – if no conversion possible
- cardinal_pythonlib.datetimefunc.coerce_to_pendulum_date(x: None | datetime | date | DateTime | str | Arrow, assume_local: bool = False, to_utc: bool = False) Date | None[source]
Converts something to a
pendulum.Date.- Parameters:
x¶ – Something that may be coercible to a date.
assume_local¶ – Governs what happens if no timezone information is present in the source object. If
True, assume local timezone; ifFalse, assume UTC.to_utc¶ – Should we return the date in UTC (e.g. London) (
True), or the date in the timezone of the source (False)? For example, 2022-02-27T23:00-05:00 (11pm in New York) is 2022-02-28T04:00Z (4am in London). Do you want the return value to be 27 Feb (to_utc=False) or 28 Feb (to_utc=True)?
- Returns:
a
pendulum.Date, orNone.- Raises:
pendulum.parsing.exceptions.ParserError – if a string fails to parse
ValueError – if no conversion possible
- cardinal_pythonlib.datetimefunc.convert_datetime_to_local(dt: None | datetime | date | DateTime | str | Arrow) DateTime[source]
Convert date/time with timezone to local timezone.
- cardinal_pythonlib.datetimefunc.convert_datetime_to_utc(dt: None | datetime | date | DateTime | str | Arrow) DateTime[source]
Convert date/time with timezone to UTC (with UTC timezone).
- cardinal_pythonlib.datetimefunc.duration_from_iso(iso_duration: str) Duration[source]
Converts an ISO-8601 format duration into a
pendulum.Duration.:raises -
isodate.isoerror.ISO8601Errorfor bad input: :raises -ValueErrorif the input had non-integer year or month values:The ISO-8601 duration format is
P[n]Y[n]M[n]DT[n]H[n]M[n]S; see https://en.wikipedia.org/wiki/ISO_8601#Durations.P = period, or duration designator, which comes first
[n]Y = number of years
[n]M = number of months
[n]W = number of weeks
[n]D = number of days
T = time designator (precedes the time component)
[n]H = number of hours
[n]M = number of minutes
[n]S = number of seconds
pendulum.Duration.minandpendulum.Duration.maxvalues areDuration(weeks=-142857142, days=-5)andDuration(weeks=142857142, days=6)respectively.isodatesupports negative durations of the format-P<something>, such as-PT5Sfor “minus 5 seconds”, but not e.g.PT-5S.I’m not clear if ISO-8601 itself supports negative durations. This suggests not: https://github.com/moment/moment/issues/2408. But lots of implementations (including to some limited extent
isodate) do support this concept.
- cardinal_pythonlib.datetimefunc.duration_to_iso(d: Duration, permit_years_months: bool = True, minus_sign_at_front: bool = True) str[source]
Converts a
pendulum.Durationinto an ISO-8601 formatted string.- Parameters:
d¶ – the duration
permit_years_months¶ –
if
False, durations with non-zero year or month components will raise aValueError; otherwise, the ISO format will always bePT<seconds>S.if
True, year/month components will be accepted, and the ISO format will beP<years>Y<months>MT<seconds>S.
minus_sign_at_front¶ –
Applies to negative durations, which probably aren’t part of the ISO standard.
if
True, the format-P<positive_duration>is used, i.e. with a minus sign at the front and individual components positive.if
False, the formatPT-<positive_seconds>S(etc.) is used, i.e. with a minus sign for each component. This format is not re-parsed successfully byisodateand will therefore failduration_from_iso().
- Raises:
ValueError –
The maximum length of the resulting string (see test code below) is:
21 if years/months are not permitted;
ill-defined if years/months are permitted, but 29 for much more than is realistic (negative, 1000 years, 11 months, and the maximum length for seconds/microseconds).
- cardinal_pythonlib.datetimefunc.format_datetime(d: None | datetime | date | DateTime | str | Arrow, fmt: str, default: str | None = None) str | None[source]
Format a datetime with a
strftimeformat specification string, or returndefaultif the input isNone.
- cardinal_pythonlib.datetimefunc.get_age(dob: None | datetime | date | DateTime | str | Arrow, when: None | datetime | date | DateTime | str | Arrow, default: str = '') int | str[source]
Age (in whole years) at a particular date, or
default.
- cardinal_pythonlib.datetimefunc.get_duration_h_m(start: str | DateTime, end: str | DateTime, default: str = 'N/A') str[source]
Calculate the time between two dates/times expressed as strings.
- cardinal_pythonlib.datetimefunc.get_now_localtz_pendulum() DateTime[source]
Get the time now in the local timezone, as a
pendulum.DateTime.
- cardinal_pythonlib.datetimefunc.get_now_utc_datetime() datetime[source]
Get the time now in the UTC timezone, as a
datetime.datetime.
- cardinal_pythonlib.datetimefunc.get_now_utc_notz_datetime() datetime[source]
Get the UTC time now, but with no timezone information, in
datetime.datetimeformat.
- cardinal_pythonlib.datetimefunc.get_now_utc_pendulum() DateTime[source]
Get the time now in the UTC timezone, as a
pendulum.DateTime.
- cardinal_pythonlib.datetimefunc.get_pendulum_duration_nonyear_nonmonth_seconds(d: Duration) float[source]
Returns the number of seconds in a
pendulum.Durationthat are NOT part of its year/month representation.Before Pendulum 2.1.1,
d.total_seconds()ignored year/month components, so this function will return the same asd.total_seconds().However, from Pendulum 2.1.1,
total_seconds()incorporates year/month information with the assumption that a year is 365 days and a month is 30 days, which is perhaps a bit iffy. This function removes that year/month component and returns the “remaining” seconds.
- cardinal_pythonlib.datetimefunc.get_tz_local() Timezone[source]
Returns the local timezone, in
pendulum.Timezone`format. (This is a subclass ofdatetime.tzinfo.)
- cardinal_pythonlib.datetimefunc.pendulum_date_to_datetime_date(x: Date) date[source]
Takes a
pendulum.Dateand returns adatetime.date. Used, for example, where a database backend insists ondatetime.date.
- cardinal_pythonlib.datetimefunc.pendulum_duration_from_isodate_duration(dur: Duration) Duration[source]
Converts a
isodate.isoduration.Durationinto apendulum.Duration.Both
isodate.isoduration.Durationandpendulum.Durationincorporate an internal representation of adatetime.timedelta(weeks, days, hours, minutes, seconds, milliseconds, microseconds) and separate representations of years and months.The
isodate.isoduration.Durationyear/month elements are both of typedecimal.Decimal– although itsstr()representation converts these silently to integer, which is quite nasty.If you create a Pendulum Duration it normalizes within its timedelta parts, but not across years and months. That is obviously because neither years and months are of exactly fixed duration.
- Raises:
ValueError –
- cardinal_pythonlib.datetimefunc.pendulum_duration_from_timedelta(td: timedelta) Duration[source]
Converts a
datetime.timedeltainto apendulum.Duration.
- cardinal_pythonlib.datetimefunc.pendulum_time_to_datetime_time(x: Time) time[source]
Takes a
pendulum.Timeand returns adatetime.time. Used, for example, where a database backend insists ondatetime.time.
- cardinal_pythonlib.datetimefunc.pendulum_to_datetime(x: DateTime) datetime[source]
Used, for example, where a database backend insists on datetime.datetime.
Compare code in
pendulum.datetime.DateTime.int_timestamp().
- cardinal_pythonlib.datetimefunc.pendulum_to_datetime_stripping_tz(x: DateTime) datetime[source]
Converts a Pendulum
DateTimeto adatetime.datetimethat has had timezone information stripped.
- cardinal_pythonlib.datetimefunc.pendulum_to_utc_datetime_without_tz(x: DateTime) datetime[source]
Converts a Pendulum
DateTime(which will have timezone information) to adatetime.datetimethat (a) has no timezone information, and (b) is in UTC.Example:
import pendulum from cardinal_pythonlib.datetimefunc import * in_moscow = pendulum.parse("2018-01-01T09:00+0300") # 9am in Moscow in_london = pendulum.UTC.convert(in_moscow) # 6am in UTC dt_utc_from_moscow = pendulum_to_utc_datetime_without_tz(in_moscow) # 6am, no timezone info dt_utc_from_london = pendulum_to_utc_datetime_without_tz(in_london) # 6am, no timezone info
- cardinal_pythonlib.datetimefunc.strfdelta(tdelta: timedelta | int | float | str, fmt='{D:02}d {H:02}h {M:02}m {S:02}s', inputtype='timedelta')[source]
Convert a
datetime.timedeltaobject or a regular number to a custom- formatted string, just like thestrftime()method does fordatetime.datetimeobjects.The
fmtargument allows custom formatting to be specified. Fields can includeseconds,minutes,hours,days, andweeks. Each field is optional.Some examples:
'{D:02}d {H:02}h {M:02}m {S:02}s' --> '05d 08h 04m 02s' (default) '{W}w {D}d {H}:{M:02}:{S:02}' --> '4w 5d 8:04:02' '{D:2}d {H:2}:{M:02}:{S:02}' --> ' 5d 8:04:02' '{H}h {S}s' --> '72h 800s'The
inputtypeargument allowstdeltato be a regular number, instead of the default behaviour of treating it as adatetime.timedeltaobject. Validinputtypestrings:'timedelta', # treats input as a datetime.timedelta 's', 'seconds', 'm', 'minutes', 'h', 'hours', 'd', 'days', 'w', 'weeks'
Modified from https://stackoverflow.com/questions/538666/python-format-timedelta-to-string