55import calendar
66import datetime
77
8- from openfisca_core import types
9-
8+ from ._errors import DateUnitValueError
109from ._units import DAY , MONTH , YEAR , ETERNITY , UNIT_WEIGHTS
1110from .instant_ import Instant
1211
1312
14- class Period (tuple ):
13+ class Period (tuple [ str , Instant , int ] ):
1514 """Toolbox to handle date intervals.
1615
1716 A ``Period`` is a triple (``unit``, ``start``, ``size``).
@@ -121,28 +120,28 @@ def __str__(self) -> str:
121120 year , month , day = start_instant
122121
123122 # 1 year long period
124- if ( unit == MONTH and size == 12 or unit == YEAR and size == 1 ) :
123+ if unit == MONTH and size == 12 or unit == YEAR and size == 1 :
125124 if month == 1 :
126125 # civil year starting from january
127126 return str (year )
128127 else :
129128 # rolling year
130- return '{ }:{}-{:02d}'. format ( YEAR , year , month )
129+ return f' { YEAR } :{ year } -{ month :02d} '
131130 # simple month
132131 if unit == MONTH and size == 1 :
133- return '{ }-{:02d}'. format ( year , month )
132+ return f' { year } -{ month :02d} '
134133 # several civil years
135134 if unit == YEAR and month == 1 :
136- return '{ }:{}:{}' . format ( unit , year , size )
135+ return f' { unit } :{ year } :{ size } '
137136
138137 if unit == DAY :
139138 if size == 1 :
140- return '{ }-{:02d}-{:02d}'. format ( year , month , day )
139+ return f' { year } -{ month :02d} -{ day :02d} '
141140 else :
142- return '{ }:{}-{:02d}-{:02d}:{}' . format ( unit , year , month , day , size )
141+ return f' { unit } :{ year } -{ month :02d} -{ day :02d} :{ size } '
143142
144143 # complex period
145- return '{ }:{}-{:02d}:{}' . format ( unit , year , month , size )
144+ return f' { unit } :{ year } -{ month :02d} :{ size } '
146145
147146 def __contains__ (self , other : object ) -> bool :
148147 """Checks if a ``period`` contains another one.
@@ -162,7 +161,7 @@ def __contains__(self, other: object) -> bool:
162161
163162 """
164163
165- if isinstance (other , types . Period ):
164+ if isinstance (other , Period ):
166165 return self .start <= other .start and self .stop >= other .stop
167166
168167 return super ().__contains__ (other )
@@ -273,10 +272,10 @@ def size_in_months(self) -> int:
273272
274273 """
275274
276- if ( self [0 ] == MONTH ) :
275+ if self [0 ] == MONTH :
277276 return self [2 ]
278277
279- if ( self [0 ] == YEAR ) :
278+ if self [0 ] == YEAR :
280279 return self [2 ] * 12
281280
282281 raise ValueError (f"Cannot calculate number of months in { self [0 ]} ." )
@@ -315,7 +314,7 @@ def size_in_days(self) -> int:
315314 raise ValueError (f"Cannot calculate number of days in { unit } " )
316315
317316 @property
318- def start (self ) -> types . Instant :
317+ def start (self ) -> Instant :
319318 """The ``Instant`` at which the ``Period`` starts.
320319
321320 Returns:
@@ -332,7 +331,7 @@ def start(self) -> types.Instant:
332331 return self [1 ]
333332
334333 @property
335- def stop (self ) -> types . Instant :
334+ def stop (self ) -> Instant :
336335 """Last day of the ``Period`` as an ``Instant``.
337336
338337 Returns:
@@ -354,7 +353,7 @@ def stop(self) -> types.Instant:
354353 year , month , day = start_instant
355354
356355 if unit == ETERNITY :
357- return Instant ((float ( "inf" ), float ( "inf" ), float ( "inf" ) ))
356+ return Instant ((1 , 1 , 1 ))
358357
359358 if unit == 'day' :
360359 if size > 1 :
@@ -375,7 +374,7 @@ def stop(self) -> types.Instant:
375374 year += 1
376375 month -= 12
377376 else :
378- assert unit == 'year' , 'Invalid unit: {} of type {}' . format ( unit , type (unit ))
377+ assert unit == 'year' , f 'Invalid unit: { unit } of type { type (unit )} '
379378 year += size
380379 day -= 1
381380 if day < 1 :
@@ -396,7 +395,7 @@ def stop(self) -> types.Instant:
396395 return Instant ((year , month , day ))
397396
398397 @property
399- def last_month (self ) -> types . Period :
398+ def last_month (self ) -> Period :
400399 """Last month of the ``Period``.
401400
402401 Returns:
@@ -407,79 +406,80 @@ def last_month(self) -> types.Period:
407406 return self .first_month .offset (- 1 )
408407
409408 @property
410- def last_3_months (self ) -> types . Period :
409+ def last_3_months (self ) -> Period :
411410 """Last 3 months of the ``Period``.
412411
413412 Returns:
414413 A Period.
415414
416415 """
417416
418- start : types . Instant = self .first_month .start
419- return self . __class__ ((MONTH , start , 3 )).offset (- 3 )
417+ start : Instant = self .first_month .start
418+ return Period ((MONTH , start , 3 )).offset (- 3 )
420419
421420 @property
422- def last_year (self ) -> types . Period :
421+ def last_year (self ) -> Period :
423422 """Last year of the ``Period``."""
424- start : types . Instant = self .start .offset ("first-of" , YEAR )
425- return self . __class__ ((YEAR , start , 1 )).offset (- 1 )
423+ start : Instant = self .start .offset ("first-of" , YEAR )
424+ return Period ((YEAR , start , 1 )).offset (- 1 )
426425
427426 @property
428- def n_2 (self ) -> types . Period :
427+ def n_2 (self ) -> Period :
429428 """Last 2 years of the ``Period``.
430429
431430 Returns:
432431 A Period.
433432
434433 """
435434
436- start : types . Instant = self .start .offset ("first-of" , YEAR )
437- return self . __class__ ((YEAR , start , 1 )).offset (- 2 )
435+ start : Instant = self .start .offset ("first-of" , YEAR )
436+ return Period ((YEAR , start , 1 )).offset (- 2 )
438437
439438 @property
440- def this_year (self ) -> types . Period :
439+ def this_year (self ) -> Period :
441440 """A new year ``Period`` starting at the beginning of the year.
442441
443442 Returns:
444443 A Period.
445444
446445 """
447446
448- start : types . Instant = self .start .offset ("first-of" , YEAR )
449- return self . __class__ ((YEAR , start , 1 ))
447+ start : Instant = self .start .offset ("first-of" , YEAR )
448+ return Period ((YEAR , start , 1 ))
450449
451450 @property
452- def first_month (self ) -> types . Period :
451+ def first_month (self ) -> Period :
453452 """A new month ``Period`` starting at the first of the month.
454453
455454 Returns:
456455 A Period.
457456
458457 """
459458
460- start : types . Instant = self .start .offset ("first-of" , MONTH )
461- return self . __class__ ((MONTH , start , 1 ))
459+ start : Instant = self .start .offset ("first-of" , MONTH )
460+ return Period ((MONTH , start , 1 ))
462461
463462 @property
464- def first_day (self ) -> types . Period :
463+ def first_day (self ) -> Period :
465464 """A new day ``Period``.
466465
467466 Returns:
468467 A Period.
469468
470469 """
471- return self . __class__ ((DAY , self .start , 1 ))
470+ return Period ((DAY , self .start , 1 ))
472471
473- def get_subperiods (self , unit : str ) -> Sequence [types . Period ]:
472+ def get_subperiods (self , unit : str ) -> Sequence [Period ]:
474473 """Return the list of all the periods of unit ``unit``.
475474
476475 Args:
477476 unit: A string representing period's ``unit``.
478477
479478 Returns:
480- A list of Periods .
479+ A list of periods .
481480
482481 Raises:
482+ DateUnitValueError: If the ``unit`` is not a valid date unit.
483483 ValueError: If the period's unit is smaller than the given unit.
484484
485485 Examples:
@@ -494,7 +494,7 @@ def get_subperiods(self, unit: str) -> Sequence[types.Period]:
494494 """
495495
496496 if UNIT_WEIGHTS [self .unit ] < UNIT_WEIGHTS [unit ]:
497- raise ValueError (' Cannot subdivide {0 } into {1}' . format ( self . unit , unit ) )
497+ raise ValueError (f" Cannot subdivide { self . unit } into { unit } " )
498498
499499 if unit == YEAR :
500500 return [self .this_year .offset (i , YEAR ) for i in range (self .size )]
@@ -505,11 +505,13 @@ def get_subperiods(self, unit: str) -> Sequence[types.Period]:
505505 if unit == DAY :
506506 return [self .first_day .offset (i , DAY ) for i in range (self .size_in_days )]
507507
508+ raise DateUnitValueError (unit )
509+
508510 def offset (
509511 self ,
510512 offset : Union [str , int ],
511513 unit : Optional [str ] = None ,
512- ) -> types . Period :
514+ ) -> Period :
513515 """Increment (or decrement) the given period with offset units.
514516
515517 Args:
@@ -534,4 +536,4 @@ def offset(
534536
535537 """
536538
537- return self . __class__ ((self [0 ], self [1 ].offset (offset , self [0 ] if unit is None else unit ), self [2 ]))
539+ return Period ((self [0 ], self [1 ].offset (offset , self [0 ] if unit is None else unit ), self [2 ]))
0 commit comments