Usage

Installation

First install package using pip:

python3 - m pip install decimaldate

DecimalDate

Note

The datetime objects used internally and being exposed by method calls ignores time (hours, minutes, and seconds) and are not timezone aware.

DecimalDate has utility and convenience methods, but for more advanced use, like determine if a date is a Saturday, or the difference in days between two dates, you can use the methods of datetime.

>>> from decimaldate import DecimalDate
>>> DecimalDate.today().as_datetime() - DecimalDate.yesterday().as_datetime()
datetime.timedelta(days=1)

For more complex datetime computations see python-dateutil,

Initialization

No argument or None

Will use today’s date:

DecimalDate()
DecimalDate(None)
int
>>> from decimaldate import DecimalDate
>>> DecimalDate(20240911)
DecimalDate(20240911)
str
>>> from decimaldate import DecimalDate
>>> DecimalDate("20240911")
DecimalDate(20240911)
decimaldate
>>> from decimaldate import DecimalDate
>>> from datetime import datetime
>>> DecimalDate(datetime.today()) == DecimalDate.today()
True

Representation

repr()
>>> from decimaldate import DecimalDate
>>> repr(DecimalDate(2024_09_11))
DecimalDate(20240911)
int()
>>> from decimaldate import DecimalDate
>>> int(DecimalDate(2024_09_11))
20240911
str()
>>> from decimaldate import DecimalDate
>>> str(DecimalDate(2024_09_11))
'20240911'

Comparisons

The usual comparison operators are available:

  • equality, ==

    >>> from decimaldate import DecimalDate
    >>> DecimalDate.today() == DecimalDate.yesterday()
    False
    
  • inequality, !=

    >>> from decimaldate import DecimalDate
    >>> DecimalDate.today() != DecimalDate.yesterday()
    True
    
  • less-than, <

    >>> from decimaldate import DecimalDate
    >>> DecimalDate.today() < DecimalDate.yesterday()
    False
    
  • less-than-or-equal, <=

    >>> from decimaldate import DecimalDate
    >>> DecimalDate.today() <= DecimalDate.yesterday()
    False
    
  • greater-than, >

    >>> from decimaldate import DecimalDate
    >>> DecimalDate.today() > DecimalDate.yesterday()
    True
    
  • greater-than-or-equal, >=

    >>> from decimaldate import DecimalDate
    >>> DecimalDate.today() >= DecimalDate.yesterday()
    True
    

Instance Methods

year()

The year of date as an integer (1-9999).

>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_11).year()
2024
month()

The month of date as an integer (1-12).

>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_11).month()
9
day()

The day of date as an integer (1-31).

>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_11).day()
11
weekday()

The day of the week as an integer (0-6), where Monday == 0 … Sunday == 6.

>>> from decimaldate import DecimalDate
>>> FRIDAY = 4
>>> DecimalDate(2024_09_27).weekday() == FRIDAY
True
isoweekday()

The day of the week as an integer (1-7), where Monday == 1 … Sunday == 7.

>>> from decimaldate import DecimalDate
>>> ISO_FRIDAY = 5
>>> DecimalDate(2024_09_27).isoweekday() == ISO_FRIDAY
True
isoformat()

The decimal date as a str formatted according to ISO (yyyy-mm-dd) and not including time or timezone.

>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_27).isoformat()
'2024-09-27'
last_day_of_month()

The last day of date’s month as an integer (1-31).

>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_11).last_day_of_month()
30
start_of_month()

A new DecimalDate instance with the date of start-of-month.

>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_11).start_of_month()
DecimalDate(20240901)
end_of_month()

A new DecimalDate instance with the date of end-of-month.

>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_11).end_of_month()
DecimalDate(20240930)
split()

Splits date into constituent year, month, and day as a tuple of integers.

>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_11).split()
(2024, 9, 11)
clone()

A new DecimalDate instance identical to original.

>>> from decimaldate import DecimalDate
>>> dd = DecimalDate(2024_09_11)
>>> clone = dd.clone()
>>> dd == clone
True
>>> dd is dd
True
>>> dd is clone
False

Note

As DecimalDate is immutable, you should consider assignment instead.

next()

A new DecimalDate instance with the day after.

>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_11).next()
DecimalDate(20240912)

If next() is given an argument it will return value days forward.

>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_11).next(42)
DecimalDate(20241023)

A negative argument is simlar to previous()

>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_11).next(-42)
DecimalDate(20240731)
>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_11).previous(42)
DecimalDate(20240731)
previous()

A new DecimalDate instance with the day before.

>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_11).previous()
DecimalDate(20240910)

If previous() is given an argument it will return value days back.

>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_11).previous(42)
DecimalDate(20240731)

A negative argument is simlar to next()

>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_11).previous(-42)
DecimalDate(20241023)
>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_11).next(42)
DecimalDate(20241023)

As other types

as_int()

int representation.

>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_11).as_int()
20240911

Similar to ìnt()

>>> from decimaldate import DecimalDate
>>> int(DecimalDate(2023_01_17))
20230117
as_str()

str representation.

>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_11).as_str()
'20240911'

Similar to str()

>>> from decimaldate import DecimalDate
>>> str(DecimalDate(2023_01_17))
'20230117'

There is an optional argument for separator.

>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_11).as_str('-')
'2024-09-11'
as_date()

datetime.date representation.

>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_27).as_date()
datetime.date(2024, 9, 27)

The returned date has no time (hours, minutes, and seconds) and is not TimeZone aware.

as_datetime()

datetime.datetime representation.

>>> from decimaldate import DecimalDate
>>> DecimalDate(2024_09_11).as_datetime()
datetime.datetime(2024, 9, 11, 0, 0)

The returned datetime has no time (hours, minutes, and seconds) and is not TimeZone aware.

The datetime representation is convenient to calculate the difference in days between two dates, or to determine if a date is a Saturday.

Class Methods

today()

A new DecimalDate instance with today’s date.

>>> from decimaldate import DecimalDate
>>> DecimalDate.today()
yesterday()

A new DecimalDate instance with yesterday’s date.

>>> from decimaldate import DecimalDate
>>> DecimalDate.yesterday()
tomorrow()

A new DecimalDate instance with tomorrows’s date.

>>> from decimaldate import DecimalDate
>>> DecimalDate.tomorrow()
range()

Return an object that produces a sequence of DecimalDate objects from start (inclusive) to stop (exclusive) by one day.

Valid argument types are (except``None``) identical to DecimalDate.

>>> for dd in DecimalDate.range(2023_05_04, 2023_05_07):
>>>     print(dd.as_str('.'))
2023.05.04
2023.05.05
2023.05.06

See DecimalDateRange.

count()

Make an iterator that returns evenly spaced decimal dates beginning with start.

>>> from decimaldate import DecimalDate
>>> for idx, dd in enumerate(DecimalDate.count(2024_03_01, 7)):
>>>     if idx >= 6:
>>>         break
>>>     print(idx, dd.isoformat())
0 2024-03-01
1 2024-03-08
2 2024-03-15
3 2024-03-22
4 2024-03-29
5 2024-04-05

Similar to itertools.count(). https://docs.python.org/3/library/itertools.html#itertools.count intended for zip() and map().

The iterator will continue until it reaches beyond valid decimal.date``values; eg. less than 1-01-01 (``datetime.MINYEAR) or greater than 9999-12-31 (datetime.MAXYEAR) and then raise OverflowError.

try_instantiate()

A new instance of DecimalDate if successful; otherwise None.

If no argument is given then uses today’s date.

Note

No errors will be raised.

>>> from decimaldate import DecimalDate
>>> DecimalDate.try_instantiate() == DecimalDate(None)
True
>>> DecimalDate.try_instantiate(None) == DecimalDate.today()
True

An invalid date will return None.

>>> from decimaldate import DecimalDate
>>> print(DecimalDate.try_instantiate(2024_27_09))
None

A valid date will instantiate a new DecimalDate.

>>> from decimaldate import DecimalDate
>>> print(DecimalDate.try_instantiate("2024_09_27"))
20240927
diff_days

Difference in days between two decimal dates.

>>> from decimaldate import DecimalDate
>>> dd1 = DecimalDate(2024_03_01)
>>> dd2 = DecimalDate(2024_03_07)
>>> diff = DecimalDate.diff_days(dd1, dd2)
>>> diff
6
>>> dd1.next(diff) == dd2
True

If the dates are identical the diffenrence is 0.

>>> from decimaldate import DecimalDate
>>> dd = DecimalDate(2024_03_01)
>>> DecimalDate.diff_days(dd, dd)
0
from_ymd

A new DecimalDate from arguments: year, month, and day.

>>> DecimalDate.from_ymd(2021,2,14)
DecimalDate(20210214)
randrange

A new DecimalDate instance randomly selected from range(start, stop, step).

Warning

As the method internally uses the random module (https://docs.python.org/3/library/random.html), the same warning applies:

The pseudo-random generators of this module should not be used for security purposes.

>>> from decimaldate import DecimalDate
>>> DecimalDate.randrange(2024_01_01, 2024_01_02, 1)
DecimalDate(20240101)

if step is 0 then raises ValueError.

if start/stop and step goes in “opposite directions” then raises ValueError.

DecimalDateRange

Intended use is by using the DecimalDate static method range().

DecimalDate.range(start, stop)
DecimalDateRange(start, stop)

will behave identically.

Creation

DecimalDateRange
>>> from decimaldate import DecimalDate, DecimalDateRange
>>> for dd in DecimalDateRange(DecimalDate(2024_02_14), DecimalDate(2024_02_17)):
>>>     print(dd)
20240214
20240215
20240216

Representation

repr()
>>> from decimaldate import DecimalDate, DecimalDateRange
>>> repr(DecimalDateRange(DecimalDate(2024_02_14), DecimalDate(2024_02_17), 3))
DecimalDateRange(20240214, 20240217, 3)

Instance Methods

start()

Start of sequence as called when initializing.

>>> from decimaldate import DecimalDateRange
>>> rng = DecimalDateRange(2024_10_01, 2024_11_01, 4)
>>> rng.start()
DecimalDate(20241001)
stop()

Stop of sequence as called when initializing.

Often different from the last DecimalDate in the sequence.

>>> from decimaldate import DecimalDateRange
>>> rng = DecimalDateRange(2024_10_01, 2024_11_01, 4)
>>> rng.stop()
DecimalDate(20241101)
>>> rng.last()
DecimalDate(20241029)
step()

Step of sequence as called when initializing.

>>> from decimaldate import DecimalDateRange
>>> rng = DecimalDateRange(2024_10_01, 2024_11_01, 4)
>>> rng.step()
4
length()

Length of sequence.

Identical to len().

>>> from decimaldate import DecimalDateRange
>>> rng = DecimalDateRange(2024_10_01, 2024_11_01, 4)
>>> list(rng)
[DecimalDate(20241001), DecimalDate(20241005), DecimalDate(20241009), DecimalDate(20241013), DecimalDate(20241017), DecimalDate(20241021), DecimalDate(20241025), DecimalDate(20241029)]
>>> rng.length()
8
>>> len(rng)
8
>>> from decimaldate import DecimalDate, DecimalDateRange
>>> rng = DecimalDateRange(DecimalDate.today(), DecimalDate.today())
>>> list(rng)
[]
>>> rng.length()
0
>>> len(rng)
0
last()

Last DecimalDate in sequence.

Often different from the stop argument.

If the sequence is empty; then returns None.

>>> from decimaldate import DecimalDateRange
>>> rng = DecimalDateRange(2024_10_01, 2024_11_01, 4)
>>> list(rng)
[DecimalDate(20241001), DecimalDate(20241005), DecimalDate(20241009), DecimalDate(20241013), DecimalDate(20241017), DecimalDate(20241021), DecimalDate(20241025), DecimalDate(20241029)]
>>> rng.last()
DecimalDate(20241029)
>>> rng.stop()
DecimalDate(20241101)
has_empty_sequence()

Convenience method similar to ddr.last() is None.

An empty sequence happens if start and stop date are identical or the step is not going the same “direction”” as the start to stop.

This behaviour is similar to the regular range().

>>> from decimaldate import DecimalDate
>>> ddr = DecimalDate.range(2023_01_23, 2023_01_23)
>>> ddr.has_empty_sequence()
True
>>> len(ddr)
0
>>> list(ddr)
[]
>>> ddr[0]
# ... IndexError
>>> from decimaldate import DecimalDateRange
>>> ddr = DecimalDateRange(2023_01_01, 2024_01_01, 7)
>>> ddr.has_empty_sequence()
False
>>> from decimaldate import DecimalDateRange
>>> ddr = DecimalDateRange(2023_01_01, 2024_01_01, -7)
>>> ddr.has_empty_sequence()
True
>>> from decimaldate import DecimalDateRange
>>> ddr = DecimalDateRange(2024_01_01, 2023_01_01, 14)
>>> ddr.has_empty_sequence()
True
>>> from decimaldate import DecimalDateRange
>>> ddr = DecimalDateRange(2024_01_01, 2023_01_01, -14)
>>> ddr.has_empty_sequence()
False
range_month_of_year_and_month

A Decimal date range starting with the first day of the month, and ends (inclusive) with the last day of the month.

>>> from decimaldate import DecimalDateRange
>>> DecimalDateRange.range_month_of_year_and_month(2024, 2)
DecimalDateRange(20240201, 20240301, 1)

Note

The end date of a range is exclusive, so will be the first day of next month.

range_month_of_decimal_date

A Decimal date range starting with the first day of the month, and ends (inclusive) with the last day of the month.

Note

The end date of a range is exclusive, so will be the first day of next month.

>>> from decimaldate import DecimalDateRange
>>> DecimalDateRange.range_month_of_decimal_date(2024_05_18)
DecimalDateRange(20240501, 20240601, 1)
>>> from decimaldate import DecimalDateRange
>>> TUESDAY = 1
>>> for dd in [
>>>     dd
>>>     for dd in DecimalDateRange.range_month_of_decimal_date(2024_02_14)
>>>     if dd.weekday() == TUESDAY
>>> ]:
>>>     print(repr(dd))
DecimalDate(20240206)
DecimalDate(20240213)
DecimalDate(20240220)
DecimalDate(20240227)