1from __future__ import annotations
2
3from dataclasses import dataclass
4from datetime import datetime
5from decimal import Decimal
6
7from isoduration.formatter import format_duration
8from isoduration.operations import add
9
10
11@dataclass
12class DateDuration:
13 years: Decimal = Decimal(0)
14 months: Decimal = Decimal(0)
15 days: Decimal = Decimal(0)
16 weeks: Decimal = Decimal(0)
17
18 def __neg__(self) -> DateDuration:
19 return DateDuration(
20 years=-self.years,
21 months=-self.months,
22 days=-self.days,
23 weeks=-self.weeks,
24 )
25
26
27@dataclass
28class TimeDuration:
29 hours: Decimal = Decimal(0)
30 minutes: Decimal = Decimal(0)
31 seconds: Decimal = Decimal(0)
32
33 def __neg__(self) -> TimeDuration:
34 return TimeDuration(
35 hours=-self.hours,
36 minutes=-self.minutes,
37 seconds=-self.seconds,
38 )
39
40
41class Duration:
42 def __init__(self, date_duration: DateDuration, time_duration: TimeDuration):
43 self.date = date_duration
44 self.time = time_duration
45
46 def __repr__(self) -> str:
47 return f"{self.__class__.__name__}({self.date}, {self.time})"
48
49 def __str__(self) -> str:
50 return format_duration(self)
51
52 def __hash__(self) -> int:
53 return hash(
54 (
55 self.date.years,
56 self.date.months,
57 self.date.days,
58 self.date.weeks,
59 self.time.hours,
60 self.time.minutes,
61 self.time.seconds,
62 )
63 )
64
65 def __eq__(self, other: object) -> bool:
66 if isinstance(other, Duration):
67 return self.date == other.date and self.time == other.time
68
69 raise NotImplementedError
70
71 def __neg__(self) -> Duration:
72 return Duration(-self.date, -self.time)
73
74 def __add__(self, other: datetime) -> datetime:
75 if isinstance(other, datetime):
76 return add(other, self)
77
78 raise NotImplementedError
79
80 __radd__ = __add__
81
82 def __sub__(self, other: object) -> None:
83 raise NotImplementedError
84
85 def __rsub__(self, other: datetime) -> datetime:
86 if isinstance(other, datetime):
87 return -self + other
88
89 raise NotImplementedError