datedict 0.1.2__py3-none-any.whl → 0.1.4__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of datedict might be problematic. Click here for more details.

datedict/DateDict.py CHANGED
@@ -1,50 +1,72 @@
1
- from datetime import date
1
+ from datetime import date, timedelta
2
2
  from decimal import Decimal
3
+ from typing import Mapping
3
4
 
4
- from datetime import timedelta
5
-
6
- from .common import ZERO
5
+ from .common import NAN, ONE, Decimable, to_decimal, ZERO
7
6
 
8
7
 
9
8
  class DateDict:
10
- def __init__(self, data=dict()):
11
- self.data: dict[str, Decimal | None] = data
12
-
13
- def create(self, start_date, end_date, value: Decimal) -> "DateDict":
9
+ def __init__(self, data: Mapping[str, Decimable] = dict(), strict: bool = True):
10
+ if not data:
11
+ raise ValueError("Data cannot be empty.")
12
+ dates = sorted(data.keys())
13
+ if strict:
14
+ # enforce contiguous coverage
15
+ if dates != [
16
+ (date.fromisoformat(dates[0]) + timedelta(days=i)).strftime("%Y-%m-%d")
17
+ for i in range(
18
+ (date.fromisoformat(dates[-1]) - date.fromisoformat(dates[0])).days
19
+ + 1
20
+ )
21
+ ]:
22
+ raise ValueError(
23
+ "Data must cover all dates in the contiguous range. "
24
+ "To disable this check, set strict=False."
25
+ )
26
+ self.start_date, self.end_date = dates[0], dates[-1]
27
+ self.data: dict[str, Decimal] = {k: to_decimal(v) for k, v in data.items()}
28
+
29
+ def fill(self, start_date, end_date, value: Decimable) -> "DateDict":
14
30
  """
15
31
  Create a new graph with a specified range and value.
16
32
  The range is defined by start_date and end_date.
17
- If the value is None, it will not be included in the graph.
18
33
  """
19
- start = (
20
- date.fromisoformat(start_date)
21
- if isinstance(start_date, str)
22
- else start_date
34
+ v = to_decimal(value)
35
+ return DateDict(
36
+ {
37
+ (date.fromisoformat(start_date) + timedelta(days=i)).strftime(
38
+ "%Y-%m-%d"
39
+ ): v
40
+ for i in range(
41
+ (date.fromisoformat(end_date) - date.fromisoformat(start_date)).days
42
+ + 1
43
+ )
44
+ }
23
45
  )
24
- end = date.fromisoformat(end_date) if isinstance(end_date, str) else end_date
25
- self.data = {
26
- date.strftime("%Y-%m-%d"): (value if value is not None else None)
27
- for date in (
28
- start + timedelta(days=i) for i in range((end - start).days + 1)
29
- )
30
- }
31
- return self
32
46
 
33
- def get(self, key: str, default: Decimal) -> Decimal:
47
+ def get(self, key: str, default: Decimal = NAN) -> Decimal:
34
48
  """
35
49
  Get the value for a specific date. If the date does not exist, return the default value.
36
50
  The date should be in the format yyyy-mm-dd.
37
51
  If the value is None, return the default value.
38
52
  """
39
- return self.data.get(key) or default
53
+ temp = self.data.get(key, NAN)
54
+ if temp.is_nan():
55
+ return default
56
+ return temp
40
57
 
41
- def __getitem__(self, key) -> Decimal | None:
42
- return self.data.get(key, None)
58
+ def __getitem__(self, key) -> Decimal:
59
+ return self.data[key]
43
60
 
44
61
  def __setitem__(self, key: str, value) -> None:
45
- self.data[key] = value
46
-
47
- def crop(self, start: str | None = None, end: str | None = None) -> "DateDict":
62
+ self.data[key] = to_decimal(value)
63
+
64
+ def crop(
65
+ self,
66
+ start: str | None = None,
67
+ end: str | None = None,
68
+ initial_value: Decimable = NAN,
69
+ ) -> "DateDict":
48
70
  """
49
71
  Crop the graph data to a specific range defined by start and end.
50
72
  If any of the parameters is None, it will not filter by that parameter.
@@ -53,85 +75,144 @@ class DateDict:
53
75
  return self
54
76
  return DateDict(
55
77
  {
56
- k: v
78
+ k: (self.get(k, to_decimal(initial_value)))
79
+ for k in map(
80
+ lambda x: x.strftime("%Y-%m-%d"),
81
+ [
82
+ (
83
+ date.fromisoformat(self.start_date)
84
+ if start is None
85
+ else date.fromisoformat(start)
86
+ )
87
+ + timedelta(days=i)
88
+ for i in range(
89
+ (
90
+ (
91
+ date.fromisoformat(self.end_date)
92
+ if end is None
93
+ else date.fromisoformat(end)
94
+ )
95
+ - (
96
+ date.fromisoformat(self.start_date)
97
+ if start is None
98
+ else date.fromisoformat(start)
99
+ )
100
+ ).days
101
+ + 1
102
+ )
103
+ ],
104
+ )
105
+ }
106
+ )
107
+
108
+ def non_negative(self) -> "DateDict":
109
+ """
110
+ Return a new DateDict with all negative values set to zero.
111
+ """
112
+ return DateDict(
113
+ {
114
+ k: (v if (not v.is_nan() and v >= ZERO) else ZERO)
57
115
  for k, v in self.data.items()
58
- if (start is None or k >= start) and (end is None or k <= end)
59
116
  }
60
117
  )
61
118
 
62
- def sum(self: "DateDict") -> Decimal:
119
+ def sum(
120
+ self: "DateDict", start: str | None = None, end: str | None = None
121
+ ) -> Decimal:
63
122
  """
64
- Calculate the sum of all values in the graph.
65
- If a value is None, it is treated as zero.
123
+ Return the sum of values in the specified range.
124
+ If a value is NaN, it is treated as zero.
66
125
  """
67
- return Decimal(
68
- sum(value if value is not None else ZERO for value in self.data.values())
126
+ s = self.start_date if start is None else start
127
+ e = self.end_date if end is None else end
128
+ return sum(
129
+ [
130
+ (self.get(k, ZERO))
131
+ for k in map(
132
+ lambda x: x.strftime("%Y-%m-%d"),
133
+ [
134
+ date.fromisoformat(s) + timedelta(days=i)
135
+ for i in range(
136
+ (date.fromisoformat(e) - date.fromisoformat(s)).days + 1
137
+ )
138
+ ],
139
+ )
140
+ ],
141
+ ZERO,
69
142
  )
70
143
 
71
- def __add__(self, other: "Decimal | DateDict") -> "DateDict":
72
- if isinstance(other, Decimal):
73
- return DateDict(
74
- {
75
- k: (v + other if v is not None else None)
76
- for k, v in self.data.items()
77
- }
78
- )
79
- else:
80
- return DateDict(
81
- {
82
- k: ((v + (other.data.get(k) or ZERO) if v is not None else None))
83
- for k, v in self.data.items()
84
- }
85
- )
86
-
87
- def __mul__(self, other: "Decimal | DateDict") -> "DateDict":
88
- if isinstance(other, Decimal):
89
- return DateDict(
90
- {
91
- k: (v * other if v is not None else None)
92
- for k, v in self.data.items()
93
- }
94
- )
144
+ def __mul__(self, other: "Decimable | DateDict") -> "DateDict":
145
+ if isinstance(other, Decimable):
146
+ return DateDict({k: v * to_decimal(other) for k, v in self.data.items()})
95
147
  elif isinstance(other, DateDict):
96
- return DateDict(
97
- {
98
- k: ((v * (other.data.get(k) or ZERO) if v is not None else None))
99
- for k, v in self.data.items()
100
- }
101
- )
102
-
103
- def __sub__(self, other: "Decimal | DateDict") -> "DateDict":
104
- return self + (other * Decimal(-1))
105
-
106
- def __truediv__(self, other: "Decimal | DateDict") -> "DateDict":
107
- if isinstance(other, Decimal):
108
- return DateDict(
109
- {
110
- k: (v / other if v is not None else None)
111
- for k, v in self.data.items()
112
- }
113
- )
114
- elif isinstance(other, DateDict):
115
- return DateDict(
116
- {
117
- k: ((v / (other.data.get(k) or ZERO) if v is not None else None))
118
- for k, v in self.data.items()
119
- }
120
- )
148
+ return DateDict({k: v * other.get(k, ONE) for k, v in self.data.items()})
149
+
150
+ def __rmul__(self, other: "Decimable | DateDict") -> "DateDict":
151
+ return self.__mul__(other)
152
+
153
+ def __neg__(self) -> "DateDict":
154
+ return self * Decimal("-1")
155
+
156
+ def __add__(self, other: "Decimable | DateDict") -> "DateDict":
157
+ if isinstance(other, Decimable):
158
+ return DateDict({k: (v + to_decimal(other)) for k, v in self.data.items()})
159
+ else:
160
+ return DateDict({k: v + other.get(k, ZERO) for k, v in self.data.items()})
161
+
162
+ def __radd__(self, other: "Decimable | DateDict") -> "DateDict":
163
+ return self.__add__(other)
164
+
165
+ def __sub__(self, other: "Decimable | DateDict") -> "DateDict":
166
+ if isinstance(other, Decimable):
167
+ return self.__add__(-to_decimal(other))
168
+ else:
169
+ return self.__add__(-other)
170
+
171
+ def __rsub__(self, other: "Decimable | DateDict") -> "DateDict":
172
+ return (-self).__add__(other)
173
+
174
+ def __truediv__(self, other: "Decimable | DateDict") -> "DateDict":
175
+ if isinstance(other, Decimable):
176
+ return DateDict({k: v / to_decimal(other) for k, v in self.data.items()})
177
+ else:
178
+ return DateDict({k: v / other.get(k, ONE) for k, v in self.data.items()})
179
+
180
+ def __eq__(self, other: object) -> bool:
181
+ if not isinstance(other, DateDict):
182
+ return False
183
+ for k in set(self.data.keys()).union(other.data.keys()):
184
+ s = self.get(k)
185
+ o = other.get(k)
186
+ if s.is_nan() and o.is_nan():
187
+ continue
188
+ if s != o:
189
+ return False
190
+ return True
191
+
192
+ def __str__(self) -> str:
193
+ return "\n".join(f"{k}: {v}" for k, v in sorted(self.data.items()))
194
+
195
+ def __repr__(self) -> str:
196
+ return f"{self.data!r}"
197
+
198
+ def to_array(self) -> list[Decimal]:
199
+ """
200
+ Convert the DateDict values to a list of Decimals, ordered by date.
201
+ """
202
+ return [self.data[k] for k in sorted(self.data.keys())]
121
203
 
122
- def to_dict(self) -> dict[str, Decimal | None]:
204
+ def to_dict(self) -> dict[str, Decimal]:
123
205
  """
124
- Convert the graph data to a dictionary.
125
- This is useful for serialization or returning as a response.
206
+ Convert the DateDict to a standard dictionary.
126
207
  """
127
- return self.data.copy()
208
+ return dict(self.data)
128
209
 
129
210
  def average(self) -> Decimal:
130
211
  """
131
- Calculate the average of all values in the graph.
132
- If there are no valid values, return Decimal(0).
212
+ Calculate the average of all values in the DateDict.
213
+ If there are no valid values, return ZERO.
133
214
  """
134
- valid_values = [v for v in self.data.values() if v is not None]
215
+ valid_values = [v for v in self.data.values() if not v.is_nan()]
135
216
  if not valid_values:
136
217
  return ZERO
137
218
  return Decimal(sum(valid_values)) / len(valid_values)
datedict/YearDict.py CHANGED
@@ -1,101 +1,133 @@
1
1
  from decimal import Decimal
2
+ from typing import Mapping
2
3
 
3
- from .common import to_decimal, ZERO
4
+ from .common import NAN, ONE, Decimable, to_decimal, ZERO
4
5
 
5
6
 
6
7
  class YearDict:
7
- def __init__(
8
- self,
9
- start_year=2025,
10
- end_year=2025,
11
- initial_value: Decimal | int | float = ZERO,
12
- ):
13
- self.start_year: int = start_year
14
- self.end_year: int = end_year
15
- iv: Decimal = to_decimal(initial_value)
16
- self.data: dict[int, Decimal] = {
17
- y: iv for y in range(self.start_year, self.end_year + 1)
18
- }
8
+ def __init__(self, data: Mapping[int, Decimable] = dict(), strict: bool = True):
9
+ if not data:
10
+ raise ValueError("Data cannot be empty.")
11
+ years = sorted(data.keys())
12
+ if strict:
13
+ # enforce contiguous coverage
14
+ if years != list(range(years[0], years[-1] + 1)):
15
+ raise ValueError(
16
+ "Data must cover all years in the contiguous range. "
17
+ "To disable this check, set strict=False."
18
+ )
19
+ self.start_year, self.end_year = years[0], years[-1]
20
+ self.data = {k: to_decimal(v) for k, v in data.items()}
21
+
22
+ def fill(self, start_year: int, end_year: int, value: Decimable) -> "YearDict":
23
+ """
24
+ Create a new graph with a specified range and value.
25
+ The range is defined by start_year and end_year.
26
+ """
27
+ v = to_decimal(value)
28
+ return YearDict({y: v for y in range(int(start_year), int(end_year) + 1)})
29
+
30
+ def get(self, year: int, default: Decimal = NAN) -> Decimal:
31
+ """
32
+ Get the value for a specific year. If the year does not exist, return the default value.
33
+ If the value is None, return the default value.
34
+ """
35
+ temp = self.data.get(year, NAN)
36
+ if temp.is_nan():
37
+ return default
38
+ return temp
19
39
 
20
40
  def __getitem__(self, year: int) -> Decimal:
21
41
  return self.data[year]
22
42
 
23
- def __setitem__(self, year: int, value):
43
+ def __setitem__(self, year: int, value) -> None:
24
44
  self.data[int(year)] = to_decimal(value)
25
45
 
26
- def override(self, data: dict[int, Decimal | float | int | str]) -> "YearDict":
27
- if not data:
28
- raise ValueError("Data cannot be empty.")
29
- ys = sorted(data.keys())
30
- # enforce contiguous coverage
31
- if ys != list(range(ys[0], ys[-1] + 1)):
32
- raise ValueError("Data must cover all years in the contiguous range.")
33
- self.start_year, self.end_year = ys[0], ys[-1] # inclusive
34
- self.data = {
35
- y: to_decimal(data[y]) for y in range(self.start_year, self.end_year + 1)
36
- }
37
- return self
38
-
39
- def fit(self, start_year: int, end_year: int, initial_value: Decimal = ZERO):
40
- self.start_year, self.end_year = int(start_year), int(end_year)
41
- iv = to_decimal(initial_value)
42
- self.data = {
43
- y: to_decimal(self.data[y]) if y in self.data else iv
44
- for y in range(self.start_year, self.end_year + 1)
45
- }
46
- return self
46
+ def crop(
47
+ self,
48
+ start: int | None = None,
49
+ end: int | None = None,
50
+ initial_value: Decimable = NAN,
51
+ ) -> "YearDict":
52
+ if start is None and end is None:
53
+ return self
54
+ return YearDict(
55
+ {
56
+ k: (self.get(k, to_decimal(initial_value)))
57
+ for k in range(
58
+ self.start_year if start is None else int(start),
59
+ self.end_year if end is None else int(end) + 1,
60
+ )
61
+ }
62
+ )
47
63
 
48
64
  def non_negative(self) -> "YearDict":
49
- out = YearDict(self.start_year, self.end_year)
50
- out.data = {y: (v if v >= ZERO else ZERO) for y, v in self.data.items()}
51
- return out
52
-
53
- def sum(
54
- self, start_year: int | None = None, end_year: int | None = None
55
- ) -> Decimal:
56
- sy = self.start_year if start_year is None else int(start_year)
57
- ey = self.end_year if end_year is None else int(end_year)
58
- return sum((self.data[y] for y in range(sy, ey + 1) if y in self.data), ZERO)
59
-
60
- def __mul__(self, other):
61
- result = YearDict(self.start_year, self.end_year)
62
- if isinstance(other, (int, float, Decimal)):
63
- result.data = {
64
- year: Decimal(value) * Decimal(str(other))
65
- for year, value in self.data.items()
65
+ """
66
+ Return a new YearDict with all negative values set to zero.
67
+ """
68
+ return YearDict(
69
+ {
70
+ y: (v if (not v.is_nan() and v >= ZERO) else ZERO)
71
+ for y, v in self.data.items()
66
72
  }
73
+ )
74
+
75
+ def sum(self, start: int | None = None, end: int | None = None) -> Decimal:
76
+ """
77
+ Return the sum of values in the specified range.
78
+ If a value is NaN, it is treated as zero.
79
+ """
80
+ s = self.start_year if start is None else start
81
+ e = self.end_year if end is None else end
82
+ return sum((self.get(y, ZERO) for y in range(s, e + 1) if y in self.data), ZERO)
83
+
84
+ def __mul__(self, other: "Decimable | YearDict") -> "YearDict":
85
+ if isinstance(other, Decimable):
86
+ return YearDict({k: v * to_decimal(other) for k, v in self.data.items()})
67
87
  elif isinstance(other, YearDict):
68
- result.data = {
69
- year: Decimal(self.data[year]) * Decimal(other.data[year])
70
- for year in self.data.keys() & other.data.keys()
71
- }
72
- else:
73
- return NotImplemented
74
- return result
88
+ return YearDict({k: v * other.get(k, ONE) for k, v in self.data.items()})
75
89
 
76
90
  def __rmul__(self, other):
77
91
  return self.__mul__(other)
78
92
 
79
- def __add__(self, other):
80
- result = YearDict(self.start_year, self.end_year)
81
- if isinstance(other, (int, float, Decimal)):
82
- result.data = {
83
- year: value + Decimal(str(other)) for year, value in self.data.items()
84
- }
93
+ def __neg__(self) -> "YearDict":
94
+ return self * Decimal("-1")
95
+
96
+ def __add__(self, other: "Decimable | YearDict") -> "YearDict":
97
+ if isinstance(other, Decimable):
98
+ return YearDict({k: v + to_decimal(other) for k, v in self.data.items()})
85
99
  elif isinstance(other, YearDict):
86
- result.data = {
87
- year: Decimal(self.data[year]) + Decimal(other.data[year])
88
- for year in self.data.keys() & other.data.keys()
89
- }
90
- else:
91
- return NotImplemented
92
- return result
100
+ return YearDict({k: v + other.get(k, ZERO) for k, v in self.data.items()})
93
101
 
94
- def __radd__(self, other):
102
+ def __radd__(self, other: "Decimable | YearDict") -> "YearDict":
95
103
  return self.__add__(other)
96
104
 
97
- def __sub__(self, other):
98
- return self.__add__(-1 * other)
105
+ def __sub__(self, other: "Decimable | YearDict") -> "YearDict":
106
+ if isinstance(other, Decimable):
107
+ return self.__add__(-to_decimal(other))
108
+ elif isinstance(other, YearDict):
109
+ return self.__add__(-other)
110
+
111
+ def __rsub__(self, other: "Decimable | YearDict") -> "YearDict":
112
+ return (-self).__add__(other)
113
+
114
+ def __truediv__(self, other: "Decimable | YearDict") -> "YearDict":
115
+ if isinstance(other, Decimable):
116
+ return YearDict({k: v / to_decimal(other) for k, v in self.data.items()})
117
+ elif isinstance(other, YearDict):
118
+ return YearDict({k: v / other.get(k, ONE) for k, v in self.data.items()})
119
+
120
+ def __eq__(self, other: object) -> bool:
121
+ if not isinstance(other, YearDict):
122
+ return False
123
+ for k in set(self.data.keys()).union(other.data.keys()):
124
+ s = self.get(k)
125
+ o = other.get(k)
126
+ if s.is_nan() and o.is_nan():
127
+ continue
128
+ if s != o:
129
+ return False
130
+ return True
99
131
 
100
132
  def __str__(self):
101
133
  return "\n".join(f"{y}: {v}" for y, v in sorted(self.data.items()))
@@ -104,7 +136,17 @@ class YearDict:
104
136
  return f"{self.data!r}"
105
137
 
106
138
  def to_array(self):
107
- return [self.data[y] for y in range(self.start_year, self.end_year + 1)]
139
+ return [self.data[k] for k in self.data.keys()]
108
140
 
109
141
  def to_dict(self):
110
142
  return dict(self.data)
143
+
144
+ def average(self) -> Decimal:
145
+ """
146
+ Return the average of the values in the YearDict.
147
+ If there are no years, return Zero
148
+ """
149
+ valid_values = [v for v in self.data.values() if not v.is_nan()]
150
+ if not valid_values:
151
+ return ZERO
152
+ return sum(valid_values, ZERO) / Decimal(len(valid_values))
datedict/__init__.py CHANGED
@@ -1,6 +1,6 @@
1
1
  from .DateDict import DateDict
2
2
  from .YearDict import YearDict
3
- from .common import ZERO
3
+ from .common import ZERO, ONE, NAN, Decimable
4
4
 
5
- __all__ = ["DateDict", "YearDict", "ZERO"]
5
+ __all__ = ["DateDict", "YearDict", "ZERO", "ONE", "NAN", "Decimable"]
6
6
  __version__ = "0.1.2"
datedict/common.py CHANGED
@@ -1,14 +1,19 @@
1
1
  from decimal import Decimal
2
+ from typing import Union
2
3
 
4
+ Decimable = Union[Decimal, str, int, float, None]
3
5
 
4
6
  ZERO = Decimal("0")
7
+ ONE = Decimal("1")
8
+ NAN = Decimal("NaN")
5
9
 
6
10
 
7
- def to_decimal(x) -> Decimal:
11
+ def to_decimal(x: Decimable) -> Decimal:
12
+ if x is None:
13
+ return Decimal("NaN")
8
14
  if isinstance(x, Decimal):
9
15
  return x
10
16
  if isinstance(x, (int, str)):
11
17
  return Decimal(x)
12
18
  if isinstance(x, float):
13
19
  return Decimal(str(x))
14
- raise TypeError(f"Unsupported type for Decimal: {type(x)}")
@@ -1,13 +1,13 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: datedict
3
- Version: 0.1.2
3
+ Version: 0.1.4
4
4
  Summary: DateDict and YearDict: date-aware dictionary structures
5
- Project-URL: Homepage, https://github.com/you/datedict
6
- Project-URL: Issues, https://github.com/you/datedict/issues
5
+ Project-URL: Homepage, https://gitlab.com/grisus/datedict
6
+ Project-URL: Issues, https://gitlab.com/grisus/datedict/-/issues
7
7
  Author-email: Lorenzo Guideri <lorenzo.guideri@dec-energy.ch>
8
8
  License: MIT License
9
9
 
10
- Copyright (c) 2025 Lorenzo Guideri
10
+ Copyright (c) 2025 DEC Energy SA
11
11
 
12
12
  Permission is hereby granted, free of charge, to any person obtaining a copy
13
13
  of this software and associated documentation files (the "Software"), to deal
@@ -0,0 +1,8 @@
1
+ datedict/DateDict.py,sha256=2UdkSp-dVFqmbFMWnlK7Ol1Gixv2koiwjWw7tw79Zhs,7776
2
+ datedict/YearDict.py,sha256=EcVg4y8Tzfgr33KjCIdoKP4GUN1GDVOrxGpHDH0ZLGQ,5494
3
+ datedict/__init__.py,sha256=4QSCqCW_owSqD3k3Oz1WAsB4p_vvzUlINroAxxFCEWQ,201
4
+ datedict/common.py,sha256=aUCsMV6roKGQIQXSFIJIN0cxAXIlK_YyRDWS1EIBu8E,424
5
+ datedict-0.1.4.dist-info/METADATA,sha256=-SL17egrcvdh_MkOPa84wvJyFUeRNQ88tlw2tvYuYwE,1991
6
+ datedict-0.1.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
+ datedict-0.1.4.dist-info/licenses/LICENSE,sha256=GMmiaNfJSsljmGtIp9lCY6V-Dkc9NDZn0jSZuAbFe7Y,1070
8
+ datedict-0.1.4.dist-info/RECORD,,
@@ -1,6 +1,6 @@
1
1
  MIT License
2
2
 
3
- Copyright (c) 2025 Lorenzo Guideri
3
+ Copyright (c) 2025 DEC Energy SA
4
4
 
5
5
  Permission is hereby granted, free of charge, to any person obtaining a copy
6
6
  of this software and associated documentation files (the "Software"), to deal
@@ -1,8 +0,0 @@
1
- datedict/DateDict.py,sha256=JrqKAJIcZL4Q7JMvzKPZQCzXGQ3wZAEkpWABAfHXLr0,4658
2
- datedict/YearDict.py,sha256=P8t43vUyOtxxABtIKf1epAU7Ohqx2-V9e9t-PyqFEh0,3798
3
- datedict/__init__.py,sha256=pZv27luenqTNoEm9jdodgCu3B5vnYdDgMYllFwCA2Sc,153
4
- datedict/common.py,sha256=yW3ohkISis4FP6baN8QJFPYHCkpVyecip7AlFg49_Kw,314
5
- datedict-0.1.2.dist-info/METADATA,sha256=p8BOciltez0gbtRl-UPsG0ihMtI4cSn5w8PBm1sNlwM,1985
6
- datedict-0.1.2.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
7
- datedict-0.1.2.dist-info/licenses/LICENSE,sha256=ULDgLM2c4o9DLMR-VEkeyuB-DRWBFX7VunJmlWShWxQ,1072
8
- datedict-0.1.2.dist-info/RECORD,,