pyutils.datetimes package
This subpackage contains code for parsing and manipulating dates, times and datetimes.
Submodules
pyutils.datetimes.constants module
Universal date/time constants.
pyutils.datetimes.dateparse_utils module
Parse dates / datetimes in a variety of formats. Some examples:
todaytomorrowyesterday21:3012:01am12:01pmlast Wednesdaythis Wednesdaynext Wedthis coming Tuesthis past Mon4 days ago4 Mondays ago4 months ago3 days back13 weeks from now1 year from now4 weeks from now3 saturdays ago4 months from today5 years from yesterday6 weeks from tomorrowapril 15, 2005april 219:30am on last Wednesday2005/apr/152005 apr 15the 1st wednesday in maythe last sun of junethis easterlast xmasChristmas, 1999next MLK dayHalloween, 20205 work days after independence day50 working days from last wed25 working days before xmastoday +1 weeksunday -3 weeks3 weeks before xmas, 19993 days before new years eve, 2000july 4ththe ides of marchthe nones of aprilthe kalends of may4 sundays before veterans’ dayxmas evethis friday at 5pmpresidents daymemorial day, 1921thanksgiving2 sun in juneaster -40 days2 days before last xmas at 3:14:15.92a3 weeks after xmas, 1995 at midday4 months before easter, 1992 at midnight5 months before halloween, 1995 at noon4 days before last wednesday44 months after today44 years before today44 weeks ago15 minutes to 3amquarter past 4pmhalf past 94 seconds to midnight4 seconds to midnight, tomorrow2021/apr/15T21:30:44.552021/apr/15 at 21:30:44.552021/4/15 at 21:30:44.552021/04/15 at 21:30:44.55Z2021/04/15 at 21:30:44.55EST13 days after last memorial day at 12 seconds before 4pm
This code is used by other code in the pyutils library such as
pyutils.argparse_utils.valid_datetime()
,
pyutils.argparse_utils.valid_date()
,
pyutils.string_utils.to_datetime()
and
pyutils.string_utils.to_date()
. This means any of these are
also able to accept and recognize this larger set of date expressions.
See the unittest for more examples and the grammar for more details.
- class pyutils.datetimes.dateparse_utils.DateParser(*, override_now_for_test_purposes=None)[source]
A class to parse dates expressed in human language (English). Example usage:
d = DateParser() d.parse('next wednesday') dt = d.get_datetime() print(dt) Wednesday 2022/10/26 00:00:00.000000
Note that the interface is somewhat klunky here because this class is conforming to interfaces auto-generated by ANTLR as it parses the grammar. See also
pyutils.string_utils.to_date()
.Construct a parser.
- Parameters:
override_now_for_test_purposes – passing a value to override_now_for_test_purposes can be used to force this parser instance to use a custom date/time for its idea of “now” so that the code can be more easily unittested. Leave as None for real use cases.
- get_date() date | None [source]
- Returns:
The date part of the last
parse()
operation again or None.- Return type:
date | None
- get_datetime(*, tz: tzinfo | None = None) datetime | None [source]
Get the datetime of the last
parse()
operation again ot None.- Parameters:
tz (tzinfo | None) – the timezone to set on output times. By default we return timezone-naive datetime objects.
- Returns:
the same datetime that
parse()
last did, optionally overriding the timezone. Returns None of no calls toparse()
have yet been made.- Return type:
datetime | None
Note
Parsed date expressions without any time part return hours = minutes = seconds = microseconds = 0 (i.e. at midnight that day). Parsed time expressions without any date part default to date = today.
- get_time() time | None [source]
- Returns:
The time part of the last
parse()
operation again or None.- Return type:
time | None
- parse(date_string: str) datetime | None [source]
Parse a ~free form date/time expression and return a timezone agnostic datetime on success. Also sets self.datetime, self.date and self.time which can each be accessed other methods on the class:
get_datetime()
,get_date()
andget_time()
. Raises a PyUtilsDateParseException with a helpful(?) message on parse error or confusion.This is the main entrypoint to this class for caller code.
To get an idea of what expressions can be parsed, check out the unittest and the grammar.
- Parameters:
date_string (str) – the string to parse
- Returns:
A datetime.datetime representing the parsed date/time or None on error.
- Raises:
PyUtilsDateParseException – an exception happened during parsing
- Return type:
datetime | None
Note
Parsed date expressions without any time part return hours = minutes = seconds = microseconds = 0 (i.e. at midnight that day). Parsed time expressions without any date part default to date = today.
Example usage:
txt = '3 weeks before last tues at 9:15am' dp = DateParser() dt1 = dp.parse(txt) dt2 = dp.get_datetime(tz=pytz.timezone('US/Pacific')) # dt1 and dt2 will be identical other than the fact that # the latter's tzinfo will be set to PST/PDT.
pyutils.datetimes.datetime_utils module
Utilities related to dates, times, and datetimes.
- class pyutils.datetimes.datetime_utils.TimeUnit(value, names=None, *, module=None, qualname=None, type=None, start=1, boundary=None)[source]
Bases:
IntEnum
An enum to represent units with which we can compute deltas.
- DAYS = 10
- FRIDAYS = 4
- HOURS = 9
- MINUTES = 8
- MONDAYS = 0
- MONTHS = 13
- SATURDAYS = 5
- SECONDS = 7
- SUNDAYS = 6
- THURSDAYS = 3
- TUESDAYS = 1
- WEDNESDAYS = 2
- WEEKS = 12
- WORKDAYS = 11
- YEARS = 14
- pyutils.datetimes.datetime_utils.add_timezone(dt: datetime, tz: tzinfo) datetime [source]
Adds a timezone to a timezone naive datetime.
- Parameters:
dt (datetime) – the datetime to insert a timezone onto
tz (tzinfo) – the timezone to insert
- Return type:
datetime
See also
replace_timezone()
,strip_timezone()
,translate_timezone()
.- Returns:
A datetime identical to dt, the input datetime, except for that a timezone has been added.
- Raises:
ValueError – if dt is already a timezone aware datetime.
- Parameters:
dt (datetime) –
tz (tzinfo) –
- Return type:
datetime
Warning
This doesn’t change the hour, minute, second, day, month, etc… of the input timezone. It simply adds a timezone to it. Adding a timezone this way will likely change the instant to which the datetime refers. See examples.
>>> now = datetime.datetime.now() >>> is_timezone_aware(now) False
>>> now_pacific = add_timezone(now, pytz.timezone('US/Pacific')) >>> is_timezone_aware(now_pacific) True
>>> "US/Pacific" in now_pacific.tzinfo.__repr__() True
>>> now.hour == now_pacific.hour True >>> now.minute == now_pacific.minute True
- pyutils.datetimes.datetime_utils.date_and_time_to_datetime(date: date, time: time) datetime [source]
Given a date and time, merge them and return a datetime.
- Parameters:
date (date) – the date component
time (time) – the time component
- Returns:
A datetime with the time component set from time and the date component set from date.
- Return type:
datetime
>>> import datetime >>> d = datetime.date(2021, 12, 25) >>> t = datetime.time(12, 30, 0, 0) >>> date_and_time_to_datetime(d, t) datetime.datetime(2021, 12, 25, 12, 30)
- pyutils.datetimes.datetime_utils.date_to_datetime(date: date) datetime [source]
Given a date, return a datetime with hour/min/sec zero (midnight)
- Arg:
date: the date desired
- Returns:
A datetime with the same month, day, and year as the input date and hours, minutes, seconds set to 12:00:00am.
- Parameters:
date (date) –
- Return type:
datetime
>>> import datetime >>> date_to_datetime(datetime.date(2021, 12, 25)) datetime.datetime(2021, 12, 25, 0, 0)
- pyutils.datetimes.datetime_utils.datetime_to_date(dt: datetime) date [source]
Return just the date part of a datetime.
- Parameters:
dt (datetime) – the datetime
- Returns:
A datetime.date with month, day and year set from input dt.
- Return type:
date
>>> import datetime >>> dt = datetime.datetime(2021, 12, 25, 12, 30) >>> datetime_to_date(dt) datetime.date(2021, 12, 25)
- pyutils.datetimes.datetime_utils.datetime_to_date_and_time(dt: datetime) Tuple[date, time] [source]
Return the component date and time objects of a datetime in a Tuple given a datetime.
- Parameters:
dt (datetime) – the datetime to decompose
- Returns:
A tuple whose first element contains a datetime.date that holds the day, month, year, etc… from the input dt and whose second element contains a datetime.time with hour, minute, second, micros, and timezone set from the input dt.
- Return type:
Tuple[date, time]
>>> import datetime >>> dt = datetime.datetime(2021, 12, 25, 12, 30) >>> (d, t) = datetime_to_date_and_time(dt) >>> d datetime.date(2021, 12, 25) >>> t datetime.time(12, 30)
- pyutils.datetimes.datetime_utils.datetime_to_minute_number(dt: datetime) MinuteOfDay [source]
Convert a datetime’s time component into a minute number (of the day). Note that this ignores the date part of the datetime and only uses the time part.
- Parameters:
dt (datetime) – the datetime whose time is to be converted
- Returns:
The minute number (of the day) that represents the input datetime’s time.
- Return type:
MinuteOfDay
>>> d = string_to_datetime( ... "2021/09/10 11:24:51AM-0700", ... )[0]
>>> datetime_to_minute_number(d) 684
- pyutils.datetimes.datetime_utils.datetime_to_string(dt: datetime, *, date_time_separator: str = ' ', include_timezone: bool = True, include_dayname: bool = False, use_month_abbrevs: bool = False, include_seconds: bool = True, include_fractional: bool = False, twelve_hour: bool = True) str [source]
A nice way to convert a datetime into a string; arguably better than just printing it and relying on it __repr__().
- Parameters:
dt (datetime) – the datetime to represent
date_time_separator (str) – the character or string to separate the date and time pieces of the representation.
include_timezone (bool) – should we include a timezone in the representation?
include_dayname (bool) – should we include the dayname (e.g. Mon) in the representation or omit it?
use_month_abbrevs (bool) – should we name the month briefly (e.g. Jan) or spell it out fully (e.g. January) in the representation?
include_seconds (bool) – should we include seconds in the time?
include_fractional (bool) – should we include micros in the time?
twelve_hour (bool) – should we use twelve or twenty-four hour time format?
- Return type:
str
>>> d = string_to_datetime( ... "2021/09/10 11:24:51AM-0700", ... )[0] >>> d datetime.datetime(2021, 9, 10, 11, 24, 51, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200))) >>> datetime_to_string(d) '2021/09/10 11:24:51AM-0700' >>> datetime_to_string(d, include_dayname=True, include_seconds=False) 'Fri/2021/09/10 11:24AM-0700'
- pyutils.datetimes.datetime_utils.datetime_to_time(dt: datetime) time [source]
Return just the time part of a datetime.
- Parameters:
dt (datetime) – the datetime
- Returns:
A datetime.time with hour, minute, second, micros, and timezone set from the input dt.
- Return type:
time
>>> import datetime >>> dt = datetime.datetime(2021, 12, 25, 12, 30) >>> datetime_to_time(dt) datetime.time(12, 30)
- pyutils.datetimes.datetime_utils.describe_duration(seconds: int, *, include_seconds: bool = False) str [source]
Describe a duration represented as a count of seconds nicely.
- Parameters:
seconds (int) – the number of seconds in the duration to be represented.
include_seconds (bool) – should we include or drop the seconds part in the representation?
- Return type:
str
Note
Of course if we drop the seconds part the result is not precise. See examples.
>>> describe_duration(182) '3 minutes'
>>> describe_duration(182, include_seconds=True) '3 minutes, and 2 seconds'
>>> describe_duration(100, include_seconds=True) '1 minute, and 40 seconds'
describe_duration(1303200) ‘15 days, 2 hours’
- pyutils.datetimes.datetime_utils.describe_duration_briefly(seconds: int, *, include_seconds: bool = False) str [source]
Describe a duration briefly.
- Parameters:
seconds (int) – the number of seconds in the duration to describe.
include_seconds (bool) – should we include seconds in our description or omit?
- Returns:
A string describing the duration represented by the input seconds briefly.
- Return type:
str
Note
Of course if we drop the seconds part the result is not precise. See examples.
>>> describe_duration_briefly(182) '3m'
>>> describe_duration_briefly(182, include_seconds=True) '3m 2s'
>>> describe_duration_briefly(100, include_seconds=True) '1m 40s'
describe_duration_briefly(1303200) ‘15d 2h’
- pyutils.datetimes.datetime_utils.describe_timedelta(delta: timedelta) str [source]
Describe a duration represented by a timedelta object.
- Parameters:
delta (timedelta) – the timedelta object that represents the duration to describe.
- Returns:
A string representation of the input duration.
- Return type:
str
Warning
Milliseconds are never included in the string representation of durations even through they may be represented by an input datetime.timedelta. Not for use when this level of precision is needed.
>>> d = datetime.timedelta(1, 600) >>> describe_timedelta(d) '1 day, and 10 minutes'
- pyutils.datetimes.datetime_utils.describe_timedelta_briefly(delta: timedelta, *, include_seconds: bool = False) str [source]
Describe a duration represented by a timedelta object.
- Parameters:
delta (timedelta) – the timedelta to describe briefly
include_seconds (bool) – should we include the second delta?
- Returns:
A string description of the input timedelta object.
- Return type:
str
Warning
Milliseconds are never included in the string representation of durations even through they may be represented by an input datetime.timedelta. Not for use when this level of precision is needed.
>>> d = datetime.timedelta(1, 600) >>> describe_timedelta_briefly(d) '1d 10m'
- pyutils.datetimes.datetime_utils.easter(year: int, method: int = 3)[source]
This method was ported from the work done by GM Arts, on top of the algorithm by Claus Tondering, which was based in part on the algorithm of Ouding (1940), as quoted in “Explanatory Supplement to the Astronomical Almanac”, P. Kenneth Seidelmann, editor.
This algorithm implements three different Easter calculation methods:
Original calculation in Julian calendar, valid in dates after 326 AD
Original method, with date converted to Gregorian calendar, valid in years 1583 to 4099
Revised method, in Gregorian calendar, valid in years 1583 to 4099 as well
These methods are represented by the constants:
EASTER_JULIAN = 1
EASTER_ORTHODOX = 2
EASTER_WESTERN = 3
The default method is method 3.
More about the algorithm may be found at:
and
- Raises:
ValueError if method argument is invalid –
- Parameters:
year (int) –
method (int) –
- pyutils.datetimes.datetime_utils.get_format_string(*, date_time_separator: str = ' ', include_timezone: bool = True, include_dayname: bool = False, use_month_abbrevs: bool = False, include_seconds: bool = True, include_fractional: bool = False, twelve_hour: bool = True) str [source]
Helper to return a format string without looking up the documentation for strftime.
- Parameters:
date_time_separator (str) – character or string to use between the date and time outputs.
include_timezone (bool) – whether or not the result should include a timezone
include_dayname (bool) – whether or not the result should incude the dayname (e.g. Monday, Wednesday, etc…)
use_month_abbrevs (bool) – whether or not to abbreviate (e.g. Jan) or spell out (e.g. January) month names.
include_seconds (bool) – whether or not to include seconds in time.
include_fractional (bool) – whether or not to include micros in time output.
twelve_hour (bool) – use twelve hour (with am/pm) or twenty four hour time format?
- Returns:
The format string for use with strftime that follows the given requirements.
- Return type:
str
>>> get_format_string() '%Y/%m/%d %I:%M:%S%p%z'
>>> get_format_string(date_time_separator='@') '%Y/%m/%d@%I:%M:%S%p%z'
>>> get_format_string(include_dayname=True) '%a/%Y/%m/%d %I:%M:%S%p%z'
>>> get_format_string(include_dayname=True, twelve_hour=False) '%a/%Y/%m/%d %H:%M:%S%z'
- pyutils.datetimes.datetime_utils.is_timezone_aware(dt: datetime) bool [source]
Checks whether a datetime is timezone aware or naive. See: https://docs.python.org/3/library/datetime.html#determining-if-an-object-is-aware-or-naive
- Parameters:
dt (datetime) – the datetime to check for timezone awareness
- Returns:
True if the datetime argument is timezone aware or False if not.
- Return type:
bool
>>> is_timezone_aware(datetime.datetime.now()) False
>>> is_timezone_aware(now_pacific()) True
- pyutils.datetimes.datetime_utils.is_timezone_naive(dt: datetime) bool [source]
Inverse of
is_timezone_aware()
. See: https://docs.python.org/3/library/datetime.html#determining-if-an-object-is-aware-or-naive- Parameters:
dt (datetime) – the datetime to check
- Returns:
True if the dt argument is timezone naive, False otherwise
- Return type:
bool
>>> is_timezone_naive(datetime.datetime.now()) True
>>> is_timezone_naive(now_pacific()) False
- pyutils.datetimes.datetime_utils.minute_number(hour: int, minute: int) MinuteOfDay [source]
Convert hour:minute into minute number from start of day. That is, if you imagine a day as a sequence of minutes from minute #0 up to minute #1439, what minute number is, e.g., 6:52am?
- Parameters:
hour (int) – the hour to convert (0 <= hour <= 23)
minute (int) – the minute to convert (0 <= minute <= 59)
- Returns:
The minute number requested. Raises ValueError on bad input.
- Raises:
ValueError – invalid hour or minute input argument
- Return type:
MinuteOfDay
>>> minute_number(0, 0) 0
>>> minute_number(9, 15) 555
>>> minute_number(23, 59) 1439
- pyutils.datetimes.datetime_utils.minute_number_to_time_string(minute_num: MinuteOfDay) str [source]
Convert minute number from start of day into hour:minute am/pm string.
- Parameters:
minute_num (MinuteOfDay) – the minute number to convert into a string
- Returns:
MM[a|p]” that represents the time that the input minute_num refers to.
- Return type:
A string of the format “HH
>>> minute_number_to_time_string(315) ' 5:15a'
>>> minute_number_to_time_string(684) '11:24a'
- pyutils.datetimes.datetime_utils.n_timeunits_from_base(count: int, unit: TimeUnit, base: datetime) datetime [source]
Return a datetime that is N units before/after a base datetime. For example:
3 Wednesdays from base datetime,
2 weeks from base date,
10 years before base datetime,
13 minutes after base datetime, etc…
- Parameters:
count (int) – signed number that indicates N units before/after the base.
unit (TimeUnit) – the timeunit that we are counting by.
base (datetime) – a datetime representing the base date the result should be relative to.
- Raises:
ValueError – unit is invalid
- Returns:
A datetime that is count units before of after the base datetime.
- Return type:
datetime
Note
To indicate before/after the base date, use a positive or negative count.
>>> base = string_to_datetime("2021/09/10 11:24:51AM-0700")[0]
The next (1) Monday from the base datetime:
>>> n_timeunits_from_base(+1, TimeUnit.MONDAYS, base) datetime.datetime(2021, 9, 13, 11, 24, 51, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200)))
Ten (10) years after the base datetime:
>>> n_timeunits_from_base(10, TimeUnit.YEARS, base) datetime.datetime(2031, 9, 10, 11, 24, 51, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200)))
Fifty (50) working days (M..F, not counting holidays) after base datetime:
>>> n_timeunits_from_base(50, TimeUnit.WORKDAYS, base) datetime.datetime(2021, 11, 23, 11, 24, 51, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200)))
Fifty (50) days (including weekends and holidays) after base datetime:
>>> n_timeunits_from_base(50, TimeUnit.DAYS, base) datetime.datetime(2021, 10, 30, 11, 24, 51, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200)))
Fifty (50) months before (note negative count) base datetime:
>>> n_timeunits_from_base(-50, TimeUnit.MONTHS, base) datetime.datetime(2017, 7, 10, 11, 24, 51, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200)))
Fifty (50) hours after base datetime:
>>> n_timeunits_from_base(50, TimeUnit.HOURS, base) datetime.datetime(2021, 9, 12, 13, 24, 51, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200)))
Fifty (50) minutes before base datetime:
>>> n_timeunits_from_base(-50, TimeUnit.MINUTES, base) datetime.datetime(2021, 9, 10, 10, 34, 51, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200)))
Fifty (50) seconds from base datetime:
>>> n_timeunits_from_base(50, TimeUnit.SECONDS, base) datetime.datetime(2021, 9, 10, 11, 25, 41, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200)))
Next month corner case – it will try to make Feb 31, 2022 then count backwards.
>>> base = string_to_datetime("2022/01/31 11:24:51AM-0700")[0] >>> n_timeunits_from_base(1, TimeUnit.MONTHS, base) datetime.datetime(2022, 2, 28, 11, 24, 51, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200)))
Last month with the same corner case
>>> base = string_to_datetime("2022/03/31 11:24:51AM-0700")[0] >>> n_timeunits_from_base(-1, TimeUnit.MONTHS, base) datetime.datetime(2022, 2, 28, 11, 24, 51, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200)))
- pyutils.datetimes.datetime_utils.now() datetime [source]
What time is it? Result is a timezone naive datetime.
- Return type:
datetime
- pyutils.datetimes.datetime_utils.now_pacific() datetime [source]
What time is it? Result in US/Pacific time (PST/PDT)
- Return type:
datetime
- pyutils.datetimes.datetime_utils.parse_duration(duration: str, raise_on_error: bool = False) int [source]
Parse a duration in string form into a delta seconds.
- Parameters:
duration (str) – a string form duration, see examples.
raise_on_error (bool) – should we raise on invalid input or just return a zero duration?
- Returns:
A count of seconds represented by the input string.
- Raises:
ValueError – bad duration and raise_on_error is set.
- Return type:
int
>>> parse_duration('15 days, 2 hours') 1303200
>>> parse_duration('15d 2h') 1303200
>>> parse_duration('100s') 100
>>> parse_duration('3min 2sec') 182
>>> parse_duration('recent') 0
>>> parse_duration('recent', raise_on_error=True) Traceback (most recent call last): ... ValueError: recent is not a valid duration.
- pyutils.datetimes.datetime_utils.replace_time_timezone(t: time, tz: tzinfo) time [source]
Replaces the timezone on a datetime.time directly without performing any translation.
- Parameters:
t (time) – the time to change the timezone on
tz (tzinfo) – the new timezone desired
- Returns:
A time with hour, minute, second, etc… identical to the input time but with timezone replaced.
- Return type:
time
Warning
This code isn’t changing the hour, minute, second, etc… of the time. It’s just messing with the timezone. Changing the timezone without changing the time causes the instant to which the datetime refers to change. For example, if passed 7:01pm PST and asked to make it EST, the result will be 7:01pm EST. See examples.
>>> t = datetime.time(8, 15, 12, 0, pytz.UTC) >>> t.tzname() 'UTC'
>>> t = replace_time_timezone(t, pytz.timezone('US/Pacific')) >>> t.tzname() 'US/Pacific'
- pyutils.datetimes.datetime_utils.replace_timezone(dt: datetime, tz: tzinfo | None) datetime [source]
Replaces the timezone on a timezone aware datetime object directly (leaving the year, month, day, hour, minute, second, micro, etc… alone). The same as calling
strip_timezone()
followed byadd_timezone()
.Works with timezone aware and timezone naive dts but for the latter it is probably better to use
add_timezone()
or just create it with a tz parameter. Using this can have weird side effects like UTC offsets that are not an even multiple of an hour, etc…- Parameters:
dt (datetime) – the datetime whose timezone should be changed
tz (tzinfo | None) – the new timezone
- Returns:
The resulting datetime. Hour, minute, second, etc… are unmodified. See warning below.
- Return type:
datetime
See also
add_timezone()
,strip_timezone()
,translate_timezone()
.Warning
This code isn’t changing the hour, minute, second, day, month, etc… of the datetime. It’s just messing with the timezone. Changing the timezone without changing the time causes the instant to which the datetime refers to change. For example, if passed 7:01pm PST and asked to make it EST, the result will be 7:01pm EST. See examples.
>>> from pytz import UTC >>> d = now_pacific() >>> d.tzinfo.tzname(d)[0] # Note: could be PST or PDT 'P' >>> h = d.hour >>> o = replace_timezone(d, UTC) >>> o.tzinfo.tzname(o) 'UTC' >>> o.hour == h True
- pyutils.datetimes.datetime_utils.seconds_to_timedelta(seconds: int) timedelta [source]
- Parameters:
seconds (int) – a count of seconds
- Returns:
A datetime.timedelta representing that count of seconds.
- Return type:
timedelta
- pyutils.datetimes.datetime_utils.string_to_datetime(txt: str, *, date_time_separator: str = ' ', include_timezone: bool = True, include_dayname: bool = False, use_month_abbrevs: bool = False, include_seconds: bool = True, include_fractional: bool = False, twelve_hour: bool = True) Tuple[datetime, str] [source]
A nice way to convert a string into a datetime. Returns both the datetime and the format string used to parse it. Also consider
pyutils.datetimes.dateparse_utils
for a full parser alternative.- Parameters:
txt (str) – the string to be converted into a datetime
date_time_separator (str) – the character or string between the time and date portions.
include_timezone (bool) – does the string include a timezone?
include_dayname (bool) – does the string include a dayname?
use_month_abbrevs (bool) – is the month abbreviated in the string (e.g. Feb) or spelled out completely (e.g. February)?
include_seconds (bool) – does the string’s time include seconds?
include_fractional (bool) – does the string’s time include micros?
twelve_hour (bool) – is the string’s time in twelve or twenty-four hour format?
- Returns:
A tuple containing the datetime parsed from string and the formatting string used to parse it.
- Return type:
Tuple[datetime, str]
>>> d = string_to_datetime( ... "2021/09/10 11:24:51AM-0700", ... ) >>> d (datetime.datetime(2021, 9, 10, 11, 24, 51, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200))), '%Y/%m/%d %I:%M:%S%p%z')
- pyutils.datetimes.datetime_utils.strip_timezone(dt: datetime) datetime [source]
Remove the timezone from a datetime. Silently ignores datetimes which are already timezone naive.
- Parameters:
dt (datetime) – the datetime to remove timezone from
- Returns:
A datetime identical to dt, the input argument, except for that the timezone has been removed.
- Return type:
datetime
See also
add_timezone()
,replace_timezone()
,translate_timezone()
.Warning
This does not change the hours, minutes, seconds, months, days, years, etc… Thus, the instant to which this timestamp refers will change when the timezone is added. See examples.
>>> now = now_pacific() >>> now.tzinfo == None False
>>> "US/Pacific" in now.tzinfo.__repr__() True
>>> dt = strip_timezone(now) >>> dt == now False
>>> dt.tzinfo == None True
>>> dt.hour == now.hour True
- pyutils.datetimes.datetime_utils.time_to_datetime_today(time: time) datetime [source]
Given a time, returns that time as a datetime with a date component set based on the current date. If the time passed is timezone aware, the resulting datetime will also be (and will use the same tzinfo). If the time is timezone naive, the datetime returned will be too.
- Parameters:
time (time) – the time desired
- Returns:
datetime with hour, minute, second, timezone set to time and day, month, year set to “today”.
- Return type:
datetime
>>> t = datetime.time(13, 14, 0) >>> d = now_pacific().date() >>> dt = time_to_datetime_today(t) >>> dt.date() == d True
>>> dt.time() == t True
>>> dt.tzinfo == t.tzinfo True
>>> dt.tzinfo == None True
>>> t = datetime.time(8, 15, 12, 0, pytz.UTC) >>> t.tzinfo == None False
>>> dt = time_to_datetime_today(t) >>> dt.tzinfo == None False
- pyutils.datetimes.datetime_utils.time_to_minute_number(t: time) MinuteOfDay [source]
Convert a datetime.time into a minute number.
- Parameters:
t (time) – a datetime.time to convert into a minute number.
- Returns:
The minute number (of the day) of the input time.
- Return type:
MinuteOfDay
>>> t = datetime.time(5, 15) >>> time_to_minute_number(t) 315
- pyutils.datetimes.datetime_utils.time_to_string(dt: datetime, *, include_seconds: bool = True, include_fractional: bool = False, include_timezone: bool = False, twelve_hour: bool = True) str [source]
A nice way to convert a datetime into a time (only) string. This ignores the date part of the datetime completely.
- Parameters:
dt (datetime) – the datetime whose time to represent
include_seconds (bool) – should seconds be included in the output?
include_fractional (bool) – should micros be included in the output?
include_timezone (bool) – should timezone be included in the output?
twelve_hour (bool) – use twelve or twenty-four hour format?
- Returns:
A string representing the time of the input datetime.
- Return type:
str
>>> d = string_to_datetime( ... "2021/09/10 11:24:51AM-0700", ... )[0] >>> d datetime.datetime(2021, 9, 10, 11, 24, 51, tzinfo=datetime.timezone(datetime.timedelta(days=-1, seconds=61200)))
>>> time_to_string(d) '11:24:51AM'
>>> time_to_string(d, include_seconds=False) '11:24AM'
>>> time_to_string(d, include_seconds=False, include_timezone=True) '11:24AM-0700'
- pyutils.datetimes.datetime_utils.timestamp() str [source]
- Returns:
A timestamp for right now in Pacific timezone.
- Return type:
str
- pyutils.datetimes.datetime_utils.timezone_abbrev_to_canonical_name(abbrev: str, country_code: str | None = 'US') str | None [source]
Return the full, unique timezone name given a timezone abbreviation and an optional country code denoting which country the timezone is located in.
- Parameters:
abbrev (str) – the timezone abbreviation, e.g. “PDT”
country_code (str | None) – optional two-letter ISO 3166-1 alpha-2 country code
- Returns:
The expanded timezone, on None if nothing found.
- Return type:
str | None
Note
This method has a predisposition to returning US-based timezones since the :param:country_code argument defaults to ‘US’.
>>> timezone_abbrev_to_canonical_name('PDT') 'America/Boise'
>>> timezone_abbrev_to_canonical_name('PST') 'America/Boise'
>>> timezone_abbrev_to_canonical_name('AKST') 'America/Nome'
>>> timezone_abbrev_to_canonical_name('+0600') 'Etc/GMT+600'
>>> timezone_abbrev_to_canonical_name('-0600') 'Etc/GMT-600'
>>> timezone_abbrev_to_canonical_name('abracadabra')
- pyutils.datetimes.datetime_utils.timezone_abbrev_to_tz(abbrev: str, country_code: str | None = 'US') DstTzInfo | StaticTzInfo | None [source]
Given a timezone abbreviation and optional country code, return a timezone from pytz that cooresponds to the given abbreviation.
- Parameters:
abbrev (str) – the timezone abbreviation, e.g. “EST”
country_code (str | None) – optional
- Returns:
A timezone from the pytz library or None on error.
- Return type:
DstTzInfo | StaticTzInfo | None
Note
This method has a predisposition to returning US-based timezones. To override this, pass an explicit country_code instead of relying on the default.
- pyutils.datetimes.datetime_utils.translate_timezone(dt: datetime, tz: tzinfo) datetime [source]
Translates dt into a different timezone by adjusting the year, month, day, hour, minute, second, micro, etc… appropriately. The returned dt is the same instant in another timezone.
- Parameters:
dt (datetime) – the datetime whose timezone should be translated.
tz (tzinfo) – the desired timezone
- Returns:
A new datetime object that represents the same instant as the input datetime but in the desired timezone. Modifies hour, minute, seconds, day, etc… as necessary for the instant to be preserved. For example, if you pass 11:01pm PST in and ask for it to be translated to EST you would get 2:01am the next day EST back out.
- Return type:
datetime
See also
replace_timezone()
,strip_timezone()
.>>> import pytz >>> d = now_pacific() >>> d.tzinfo.tzname(d)[0] # Note: could be PST or PDT 'P' >>> h = d.hour >>> o = translate_timezone(d, pytz.timezone('US/Eastern')) >>> o.tzinfo.tzname(o)[0] # Again, could be EST or EDT 'E' >>> o.hour == h False >>> expected = h + 3 # Three hours later in E?T than P?T >>> expected = expected % 24 # Handle edge case >>> expected == o.hour True