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.timedelta
takes parameters from microseconds to weeks; these are all exact.isodate.isoduration.Duration
also 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.Duration
has 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 raiseValueError
orOverflowError
(as per https://dateutil.readthedocs.org/en/latest/parser.html).See also
coerce_to_pendulum_date()
, noting thatpendulum.Date
is 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 raiseValueError
orOverflowError
(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.ISO8601Error
for bad input: :raises -ValueError
if 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.min
andpendulum.Duration.max
values areDuration(weeks=-142857142, days=-5)
andDuration(weeks=142857142, days=6)
respectively.isodate
supports negative durations of the format-P<something>
, such as-PT5S
for “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.Duration
into 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 byisodate
and 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
strftime
format specification string, or returndefault
if 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.datetime
format.
- 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.Duration
that 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.Date
and 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.Duration
into apendulum.Duration
.Both
isodate.isoduration.Duration
andpendulum.Duration
incorporate an internal representation of adatetime.timedelta
(weeks, days, hours, minutes, seconds, milliseconds, microseconds) and separate representations of years and months.The
isodate.isoduration.Duration
year/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.timedelta
into apendulum.Duration
.
- cardinal_pythonlib.datetimefunc.pendulum_time_to_datetime_time(x: Time) time [source]
Takes a
pendulum.Time
and 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
DateTime
to adatetime.datetime
that 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.datetime
that (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.timedelta
object or a regular number to a custom- formatted string, just like thestrftime()
method does fordatetime.datetime
objects.The
fmt
argument 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
inputtype
argument allowstdelta
to be a regular number, instead of the default behaviour of treating it as adatetime.timedelta
object. Validinputtype
strings:'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