1+ from __future__ import annotations
2+
3+ from typing import Union
4+
15import calendar
26import datetime
37
610
711
812class Instant (tuple ):
9- """An instant in time (year, month, day).
13+ """An instant in time (`` year``, `` month``, `` day`` ).
1014
11- An :class:`. Instant` represents the most atomic and indivisible
12- legislation's time unit.
15+ An `` Instant` ` represents the most atomic and indivisible
16+ legislation's date unit.
1317
1418 Current implementation considers this unit to be a day, so
15- :obj:` instants <.Instant> ` can be thought of as "day dates".
19+ `` instants` ` can be thought of as "day dates".
1620
1721 Args:
18- (tuple(tuple( int, int, int) )):
22+ (tuple(int, int, int)):
1923 The ``year``, ``month``, and ``day``, accordingly.
2024
2125 Examples:
2226 >>> instant = Instant((2021, 9, 13))
2327
24- >>> repr(Instant)
25- "<class 'openfisca_core.periods.instant_.Instant'>"
28+ ``Instants`` are represented as a ``tuple`` containing the date units:
2629
2730 >>> repr(instant)
2831 'Instant((2021, 9, 13))'
2932
33+ However, their user-friendly representation is as a date in the
34+ ISO format:
35+
3036 >>> str(instant)
3137 '2021-09-13'
3238
39+ Because ``Instants`` are ``tuples``, they are immutable, which allows
40+ us to use them as keys in hashmaps:
41+
3342 >>> dict([(instant, (2021, 9, 13))])
3443 {Instant((2021, 9, 13)): (2021, 9, 13)}
3544
36- >>> list(instant)
37- [2021, 9, 13]
45+ All the rest of the ``tuple`` protocols are inherited as well:
3846
3947 >>> instant[0]
4048 2021
@@ -48,74 +56,102 @@ class Instant(tuple):
4856 >>> instant == (2021, 9, 13)
4957 True
5058
51- >>> instant != (2021, 9, 13)
52- False
53-
5459 >>> instant > (2020, 9, 13)
5560 True
5661
57- >>> instant < (2020, 9, 13)
58- False
59-
60- >>> instant >= (2020, 9, 13)
61- True
62-
63- >>> instant <= (2020, 9, 13)
64- False
65-
66- >>> instant.year
67- 2021
68-
69- >>> instant.month
70- 9
71-
72- >>> instant.day
73- 13
74-
75- >>> instant.date
76- datetime.date(2021, 9, 13)
77-
7862 >>> year, month, day = instant
7963
8064 """
8165
82- def __repr__ (self ):
66+ def __repr__ (self ) -> str :
8367 return '{}({})' .format (self .__class__ .__name__ , super (Instant , self ).__repr__ ())
8468
85- def __str__ (self ):
69+ def __str__ (self ) -> str :
8670 instant_str = config .str_by_instant_cache .get (self )
8771 if instant_str is None :
8872 config .str_by_instant_cache [self ] = instant_str = self .date .isoformat ()
8973 return instant_str
9074
9175 @property
92- def date (self ):
76+ def date (self ) -> "datetime.date" :
77+ """The date representation of the ``Instant``.
78+
79+ Example:
80+ >>> instant = Instant((2021, 10, 1))
81+ >>> instant.date
82+ datetime.date(2021, 10, 1)
83+
84+ Returns:
85+ A datetime.time.
86+
87+ """
88+
9389 instant_date = config .date_by_instant_cache .get (self )
9490 if instant_date is None :
9591 config .date_by_instant_cache [self ] = instant_date = datetime .date (* self )
9692 return instant_date
9793
9894 @property
99- def day (self ):
100- return self [2 ]
95+ def year (self ) -> int :
96+ """The ``year`` of the ``Instant``.
97+
98+ Example:
99+ >>> instant = Instant((2021, 10, 1))
100+ >>> instant.year
101+ 2021
102+
103+ Returns:
104+ An int.
105+
106+ """
107+
108+ return self [0 ]
101109
102110 @property
103- def month (self ):
111+ def month (self ) -> int :
112+ """The ``month`` of the ``Instant``.
113+
114+ Example:
115+ >>> instant = Instant((2021, 10, 1))
116+ >>> instant.month
117+ 10
118+
119+ Returns:
120+ An int.
121+
122+ """
123+
104124 return self [1 ]
105125
106- def period (self , unit , size = 1 ):
107- """Creates a new :obj:`.Period` starting at :obj:`.Instant`.
126+ @property
127+ def day (self ) -> int :
128+ """The ``day`` of the ``Instant``.
129+
130+ Example:
131+ >>> instant = Instant((2021, 10, 1))
132+ >>> instant.day
133+ 1
134+
135+ Returns:
136+ An int.
137+
138+ """
139+
140+ return self [2 ]
141+
142+ def period (self , unit : str , size : int = 1 ) -> "periods.Period" :
143+ """Creates a new ``Period`` starting at ``self``.
108144
109145 Args:
110- unit: ``day`` or ``month`` or ``year``.
111- size: How many of ``unit``.
146+ unit (str) : ``day`` or ``month`` or ``year``.
147+ size (int) : How many of ``unit``.
112148
113149 Returns:
114- A new object :obj:`.Period` .
150+ Period: A new one .
115151
116152 Raises:
117- :exc:` AssertionError` : When ``unit`` is not a date unit.
118- :exc:` AssertionError` : When ``size`` is not an unsigned :obj:` int`.
153+ AssertionError: When ``unit`` is not a date unit.
154+ AssertionError: When ``size`` is not an unsigned `` int` `.
119155
120156 Examples:
121157 >>> Instant((2021, 9, 13)).period("year")
@@ -130,20 +166,20 @@ def period(self, unit, size = 1):
130166 assert isinstance (size , int ) and size >= 1 , 'Invalid size: {} of type {}' .format (size , type (size ))
131167 return periods .Period ((unit , self , size ))
132168
133- def offset (self , offset , unit ) :
169+ def offset (self , offset : Union [ str , int ], unit : str ) -> "Instant" :
134170 """Increments/decrements the given instant with offset units.
135171
136172 Args:
137- offset: How much of ``unit`` to offset.
138- unit: What to offset
173+ offset (str | int) : How much of ``unit`` to offset.
174+ unit (str) : What to offset.
139175
140176 Returns:
141- :obj:`. Instant` : A new :obj:`.Instant` in time .
177+ Instant: A new one .
142178
143179 Raises:
144- :exc:` AssertionError` : When ``unit`` is not a date unit.
145- :exc:` AssertionError` : When ``offset`` is not either ``first-of``,
146- ``last-of``, or any :obj:` int`.
180+ AssertionError: When ``unit`` is not a date unit.
181+ AssertionError: When ``offset`` is not either ``first-of``,
182+ ``last-of``, or any `` int` `.
147183
148184 Examples:
149185 >>> Instant((2020, 12, 31)).offset("first-of", "month")
@@ -215,7 +251,3 @@ def offset(self, offset, unit):
215251 day = month_last_day
216252
217253 return self .__class__ ((year , month , day ))
218-
219- @property
220- def year (self ):
221- return self [0 ]
0 commit comments