infdate 0.2.1__tar.gz → 0.2.2__tar.gz
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.
- {infdate-0.2.1 → infdate-0.2.2}/PKG-INFO +55 -37
- {infdate-0.2.1 → infdate-0.2.2}/README.md +52 -35
- {infdate-0.2.1 → infdate-0.2.2}/pyproject.toml +3 -2
- infdate-0.2.2/reports/docs/build-info.json +8 -0
- {infdate-0.2.1 → infdate-0.2.2}/reports/docs/build-info.md +2 -2
- infdate-0.2.2/reports/test-junit.xml +1 -0
- {infdate-0.2.1 → infdate-0.2.2}/src/infdate/__init__.py +22 -18
- {infdate-0.2.1 → infdate-0.2.2}/tests/test_infdate.py +148 -64
- infdate-0.2.1/reports/docs/build-info.json +0 -8
- infdate-0.2.1/reports/test-junit.xml +0 -1
- {infdate-0.2.1 → infdate-0.2.2}/.gitignore +0 -0
- {infdate-0.2.1 → infdate-0.2.2}/.gitlab-ci.yml +0 -0
- {infdate-0.2.1 → infdate-0.2.2}/LICENSE +0 -0
- {infdate-0.2.1 → infdate-0.2.2}/src/infdate/py.typed +0 -0
- {infdate-0.2.1 → infdate-0.2.2}/tests/__init__.py +0 -0
- {infdate-0.2.1 → infdate-0.2.2}/tools/ci_get_pypi_token.py +0 -0
- {infdate-0.2.1 → infdate-0.2.2}/tools/codestyle.sh +0 -0
- {infdate-0.2.1 → infdate-0.2.2}/tools/pytest.sh +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: infdate
|
3
|
-
Version: 0.2.
|
3
|
+
Version: 0.2.2
|
4
4
|
Summary: Date object wrapper supporting infinity
|
5
5
|
Project-URL: Homepage, https://gitlab.com/blackstream-x/infdate
|
6
6
|
Project-URL: CI, https://gitlab.com/blackstream-x/infdate/-/pipelines
|
@@ -14,12 +14,13 @@ Classifier: License :: OSI Approved :: MIT License
|
|
14
14
|
Classifier: Operating System :: OS Independent
|
15
15
|
Classifier: Programming Language :: Python :: 3
|
16
16
|
Classifier: Programming Language :: Python :: 3 :: Only
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
17
18
|
Classifier: Programming Language :: Python :: 3.11
|
18
19
|
Classifier: Programming Language :: Python :: 3.12
|
19
20
|
Classifier: Programming Language :: Python :: 3.13
|
20
21
|
Classifier: Programming Language :: Python :: 3.14
|
21
22
|
Classifier: Topic :: Software Development :: Libraries :: Python Modules
|
22
|
-
Requires-Python: >=3.
|
23
|
+
Requires-Python: >=3.10
|
23
24
|
Description-Content-Type: text/markdown
|
24
25
|
|
25
26
|
# infdate
|
@@ -35,14 +36,18 @@ _Python module for date calculations implementing a concept of infinity_
|
|
35
36
|
└── RealDate
|
36
37
|
|
37
38
|
|
38
|
-
The base class **GenericDate** should not be instantiated
|
39
|
+
The base class **GenericDate** should not be instantiated
|
40
|
+
but can be used as a type annotation. In fact, it should be preferred
|
41
|
+
over the other classes in typing annotations.
|
39
42
|
|
40
43
|
**InfinityDate** can represent either positive or negative infinity.
|
41
44
|
The module-level constants **MIN** and **MAX** contain the two possible
|
42
45
|
**InfinityDate** instance variations.
|
43
46
|
|
44
47
|
**RealDate** instances represent real dates like the standard library’s
|
45
|
-
**datetime.date** class, with mostly equal or similar semantics.
|
48
|
+
**[datetime.date]** class, with mostly equal or similar semantics.
|
49
|
+
The module -level constants **REAL_MIN** and **REAL_MAX** are the eqivalents
|
50
|
+
of **datetime.date.min** and **datetime.date.max** as **RealDate** instances.
|
46
51
|
|
47
52
|
For any valid **RealDate** instance, the following is **True**:
|
48
53
|
|
@@ -50,9 +55,21 @@ For any valid **RealDate** instance, the following is **True**:
|
|
50
55
|
infdate.MIN < infdate.REAL_MIN <= real_date_instance <= infdate.REAL_MAX < infdate.MAX
|
51
56
|
```
|
52
57
|
|
53
|
-
### Module-level
|
58
|
+
### Module-level constants
|
59
|
+
|
60
|
+
* **MIN** = **InfinityDate(**_past_bound_=`True`**)** → the beginning of time
|
61
|
+
* **MAX** = **InfinityDate(**_past_bound_=`False`**)** → the end of time
|
62
|
+
* **MIN_ORDINAL** = `1` → same as **datetime.date.min.toordinal()**
|
63
|
+
* **MAX_ORDINAL** = `3652059` → same as **datetime.date.max.toordinal()**
|
64
|
+
* **REAL_MIN** = **fromordinal(MIN_ORDINAL)**
|
65
|
+
→ represents _0001-01-01_, the same date as **datetime.date.min**
|
66
|
+
* **REAL_MAX** = **fromordinal(MAX_ORDINAL)**
|
67
|
+
→ represents _9999-12-31_, the same date as **datetime.date.max**
|
68
|
+
* **RESOLUTION** = `1` → represents the lowest possible date difference: _one day_
|
54
69
|
|
55
70
|
|
71
|
+
### Module-level factory functions
|
72
|
+
|
56
73
|
The following factory methods from the **datetime.date** class
|
57
74
|
are provided as module-level functions:
|
58
75
|
|
@@ -78,15 +95,17 @@ Two additional factory functions are provided:
|
|
78
95
|
|
79
96
|
Some notable difference from the **datetime.date** class, mainly due to the design decision to express date differences in pure numbers (ie. **float** because **math.inf** also is a float):
|
80
97
|
|
81
|
-
*
|
98
|
+
* infdate classes have no **max**, **min** or **resolution** attributes,
|
99
|
+
but there are [module-level constants] serving the same purpose.
|
82
100
|
|
83
|
-
* The **
|
84
|
-
but also represents exactly one day.
|
101
|
+
* The **.toordinal()** method returns **int**, **math.inf**, or **-math.inf**.
|
85
102
|
|
86
|
-
* Subtracting a date from an **InfinityDate** or **RealDate** always returns
|
103
|
+
* Subtracting a date from an **InfinityDate** or **RealDate** always returns
|
104
|
+
an **int**, **math.inf**, or **-math.inf** instead of a **datetime.timedelta** instance.
|
87
105
|
|
88
106
|
* Likewise, you cannot add or subtract **datetime.timedelta** instances
|
89
|
-
from an **InfinityDate** or **RealDate**, only **float** or **int**
|
107
|
+
from an **InfinityDate** or **RealDate**, only **float** or **int**
|
108
|
+
(support for adding and subtracting datetime.timedelta instances might be added in the future, [see the feature request]).
|
90
109
|
|
91
110
|
|
92
111
|
## Example usage
|
@@ -95,22 +114,20 @@ Some notable difference from the **datetime.date** class, mainly due to the desi
|
|
95
114
|
>>> import infdate
|
96
115
|
>>> today = infdate.today()
|
97
116
|
>>> today
|
98
|
-
RealDate(2025, 6,
|
99
|
-
>>> print(today)
|
100
|
-
|
101
|
-
>>> print(f"US date notation {today:%m/%d/%y}")
|
102
|
-
US date notation 06/25/25
|
117
|
+
RealDate(2025, 6, 27)
|
118
|
+
>>> print(f"US date notation: {today:%m/%d/%y}")
|
119
|
+
US date notation: 06/27/25
|
103
120
|
>>> today.ctime()
|
104
|
-
'
|
121
|
+
'Fri Jun 27 00:00:00 2025'
|
105
122
|
>>> today.isocalendar()
|
106
|
-
datetime.IsoCalendarDate(year=2025, week=26, weekday=
|
123
|
+
datetime.IsoCalendarDate(year=2025, week=26, weekday=5)
|
107
124
|
>>>
|
108
125
|
>>> yesterday = today - 1
|
109
126
|
>>> yesterday.ctime()
|
110
|
-
'
|
127
|
+
'Thu Jun 26 00:00:00 2025'
|
111
128
|
>>>
|
112
129
|
>>> today - yesterday
|
113
|
-
1
|
130
|
+
1
|
114
131
|
>>> infdate.MIN
|
115
132
|
InfinityDate(past_bound=True)
|
116
133
|
>>> infdate.MAX
|
@@ -123,25 +140,26 @@ inf
|
|
123
140
|
|
124
141
|
**InfinityDate** and **RealDate** instances can be compared with each other, and also with **datetime.date** instances.
|
125
142
|
|
126
|
-
Subtracting
|
127
|
-
currently still raises a **TypeError**):
|
128
|
-
|
129
|
-
>>> from datetime import date
|
130
|
-
>>> stdlib_today = date.today()
|
131
|
-
>>> today == stdlib_today
|
132
|
-
True
|
133
|
-
>>> yesterday < stdlib_today
|
134
|
-
True
|
135
|
-
>>> yesterday - stdlib_today
|
136
|
-
-1.0
|
137
|
-
>>> stdlib_today - yesterday
|
138
|
-
Traceback (most recent call last):
|
139
|
-
File "<python-input-22>", line 1, in <module>
|
140
|
-
stdlib_today - yesterday
|
141
|
-
~~~~~~~~~~~~~^~~~~~~~~~~
|
142
|
-
TypeError: unsupported operand type(s) for -: 'datetime.date' and 'RealDate'
|
143
|
+
Subtracting **InfinityDate** or **RealDate** and **datetime.date** instances from each other also works:
|
143
144
|
|
145
|
+
``` pycon
|
146
|
+
>>> from datetime import date
|
147
|
+
>>> stdlib_today = date.today()
|
148
|
+
>>> today == stdlib_today
|
149
|
+
True
|
150
|
+
>>> yesterday < stdlib_today
|
151
|
+
True
|
152
|
+
>>> yesterday - stdlib_today
|
153
|
+
-1
|
154
|
+
>>> stdlib_today - yesterday
|
155
|
+
1
|
156
|
+
>>> stdlib_today - infdate.MIN
|
157
|
+
inf
|
158
|
+
```
|
144
159
|
|
145
160
|
|
146
161
|
* * *
|
147
|
-
[
|
162
|
+
[datetime.date]: https://docs.python.org/3/library/datetime.html#date-objects
|
163
|
+
[Personal Access Tokens API]: https://docs.gitlab.com/api/personal_access_tokens/
|
164
|
+
[module-level constants]: #module-level-constants
|
165
|
+
[see the feature request]: https://gitlab.com/blackstream-x/infdate/-/issues/6
|
@@ -11,14 +11,18 @@ _Python module for date calculations implementing a concept of infinity_
|
|
11
11
|
└── RealDate
|
12
12
|
|
13
13
|
|
14
|
-
The base class **GenericDate** should not be instantiated
|
14
|
+
The base class **GenericDate** should not be instantiated
|
15
|
+
but can be used as a type annotation. In fact, it should be preferred
|
16
|
+
over the other classes in typing annotations.
|
15
17
|
|
16
18
|
**InfinityDate** can represent either positive or negative infinity.
|
17
19
|
The module-level constants **MIN** and **MAX** contain the two possible
|
18
20
|
**InfinityDate** instance variations.
|
19
21
|
|
20
22
|
**RealDate** instances represent real dates like the standard library’s
|
21
|
-
**datetime.date** class, with mostly equal or similar semantics.
|
23
|
+
**[datetime.date]** class, with mostly equal or similar semantics.
|
24
|
+
The module -level constants **REAL_MIN** and **REAL_MAX** are the eqivalents
|
25
|
+
of **datetime.date.min** and **datetime.date.max** as **RealDate** instances.
|
22
26
|
|
23
27
|
For any valid **RealDate** instance, the following is **True**:
|
24
28
|
|
@@ -26,9 +30,21 @@ For any valid **RealDate** instance, the following is **True**:
|
|
26
30
|
infdate.MIN < infdate.REAL_MIN <= real_date_instance <= infdate.REAL_MAX < infdate.MAX
|
27
31
|
```
|
28
32
|
|
29
|
-
### Module-level
|
33
|
+
### Module-level constants
|
34
|
+
|
35
|
+
* **MIN** = **InfinityDate(**_past_bound_=`True`**)** → the beginning of time
|
36
|
+
* **MAX** = **InfinityDate(**_past_bound_=`False`**)** → the end of time
|
37
|
+
* **MIN_ORDINAL** = `1` → same as **datetime.date.min.toordinal()**
|
38
|
+
* **MAX_ORDINAL** = `3652059` → same as **datetime.date.max.toordinal()**
|
39
|
+
* **REAL_MIN** = **fromordinal(MIN_ORDINAL)**
|
40
|
+
→ represents _0001-01-01_, the same date as **datetime.date.min**
|
41
|
+
* **REAL_MAX** = **fromordinal(MAX_ORDINAL)**
|
42
|
+
→ represents _9999-12-31_, the same date as **datetime.date.max**
|
43
|
+
* **RESOLUTION** = `1` → represents the lowest possible date difference: _one day_
|
30
44
|
|
31
45
|
|
46
|
+
### Module-level factory functions
|
47
|
+
|
32
48
|
The following factory methods from the **datetime.date** class
|
33
49
|
are provided as module-level functions:
|
34
50
|
|
@@ -54,15 +70,17 @@ Two additional factory functions are provided:
|
|
54
70
|
|
55
71
|
Some notable difference from the **datetime.date** class, mainly due to the design decision to express date differences in pure numbers (ie. **float** because **math.inf** also is a float):
|
56
72
|
|
57
|
-
*
|
73
|
+
* infdate classes have no **max**, **min** or **resolution** attributes,
|
74
|
+
but there are [module-level constants] serving the same purpose.
|
58
75
|
|
59
|
-
* The **
|
60
|
-
but also represents exactly one day.
|
76
|
+
* The **.toordinal()** method returns **int**, **math.inf**, or **-math.inf**.
|
61
77
|
|
62
|
-
* Subtracting a date from an **InfinityDate** or **RealDate** always returns
|
78
|
+
* Subtracting a date from an **InfinityDate** or **RealDate** always returns
|
79
|
+
an **int**, **math.inf**, or **-math.inf** instead of a **datetime.timedelta** instance.
|
63
80
|
|
64
81
|
* Likewise, you cannot add or subtract **datetime.timedelta** instances
|
65
|
-
from an **InfinityDate** or **RealDate**, only **float** or **int**
|
82
|
+
from an **InfinityDate** or **RealDate**, only **float** or **int**
|
83
|
+
(support for adding and subtracting datetime.timedelta instances might be added in the future, [see the feature request]).
|
66
84
|
|
67
85
|
|
68
86
|
## Example usage
|
@@ -71,22 +89,20 @@ Some notable difference from the **datetime.date** class, mainly due to the desi
|
|
71
89
|
>>> import infdate
|
72
90
|
>>> today = infdate.today()
|
73
91
|
>>> today
|
74
|
-
RealDate(2025, 6,
|
75
|
-
>>> print(today)
|
76
|
-
|
77
|
-
>>> print(f"US date notation {today:%m/%d/%y}")
|
78
|
-
US date notation 06/25/25
|
92
|
+
RealDate(2025, 6, 27)
|
93
|
+
>>> print(f"US date notation: {today:%m/%d/%y}")
|
94
|
+
US date notation: 06/27/25
|
79
95
|
>>> today.ctime()
|
80
|
-
'
|
96
|
+
'Fri Jun 27 00:00:00 2025'
|
81
97
|
>>> today.isocalendar()
|
82
|
-
datetime.IsoCalendarDate(year=2025, week=26, weekday=
|
98
|
+
datetime.IsoCalendarDate(year=2025, week=26, weekday=5)
|
83
99
|
>>>
|
84
100
|
>>> yesterday = today - 1
|
85
101
|
>>> yesterday.ctime()
|
86
|
-
'
|
102
|
+
'Thu Jun 26 00:00:00 2025'
|
87
103
|
>>>
|
88
104
|
>>> today - yesterday
|
89
|
-
1
|
105
|
+
1
|
90
106
|
>>> infdate.MIN
|
91
107
|
InfinityDate(past_bound=True)
|
92
108
|
>>> infdate.MAX
|
@@ -99,25 +115,26 @@ inf
|
|
99
115
|
|
100
116
|
**InfinityDate** and **RealDate** instances can be compared with each other, and also with **datetime.date** instances.
|
101
117
|
|
102
|
-
Subtracting
|
103
|
-
currently still raises a **TypeError**):
|
104
|
-
|
105
|
-
>>> from datetime import date
|
106
|
-
>>> stdlib_today = date.today()
|
107
|
-
>>> today == stdlib_today
|
108
|
-
True
|
109
|
-
>>> yesterday < stdlib_today
|
110
|
-
True
|
111
|
-
>>> yesterday - stdlib_today
|
112
|
-
-1.0
|
113
|
-
>>> stdlib_today - yesterday
|
114
|
-
Traceback (most recent call last):
|
115
|
-
File "<python-input-22>", line 1, in <module>
|
116
|
-
stdlib_today - yesterday
|
117
|
-
~~~~~~~~~~~~~^~~~~~~~~~~
|
118
|
-
TypeError: unsupported operand type(s) for -: 'datetime.date' and 'RealDate'
|
118
|
+
Subtracting **InfinityDate** or **RealDate** and **datetime.date** instances from each other also works:
|
119
119
|
|
120
|
+
``` pycon
|
121
|
+
>>> from datetime import date
|
122
|
+
>>> stdlib_today = date.today()
|
123
|
+
>>> today == stdlib_today
|
124
|
+
True
|
125
|
+
>>> yesterday < stdlib_today
|
126
|
+
True
|
127
|
+
>>> yesterday - stdlib_today
|
128
|
+
-1
|
129
|
+
>>> stdlib_today - yesterday
|
130
|
+
1
|
131
|
+
>>> stdlib_today - infdate.MIN
|
132
|
+
inf
|
133
|
+
```
|
120
134
|
|
121
135
|
|
122
136
|
* * *
|
123
|
-
[
|
137
|
+
[datetime.date]: https://docs.python.org/3/library/datetime.html#date-objects
|
138
|
+
[Personal Access Tokens API]: https://docs.gitlab.com/api/personal_access_tokens/
|
139
|
+
[module-level constants]: #module-level-constants
|
140
|
+
[see the feature request]: https://gitlab.com/blackstream-x/infdate/-/issues/6
|
@@ -1,17 +1,18 @@
|
|
1
1
|
[project]
|
2
2
|
name = "infdate"
|
3
|
-
version = "0.2.
|
3
|
+
version = "0.2.2"
|
4
4
|
description = "Date object wrapper supporting infinity"
|
5
5
|
readme = "README.md"
|
6
6
|
authors = [
|
7
7
|
{ name = "Rainer Schwarzbach", email = "rainer@blackstream.de" },
|
8
8
|
]
|
9
|
-
requires-python = ">=3.
|
9
|
+
requires-python = ">=3.10"
|
10
10
|
classifiers = [
|
11
11
|
"Development Status :: 4 - Beta",
|
12
12
|
"License :: OSI Approved :: MIT License",
|
13
13
|
"Operating System :: OS Independent",
|
14
14
|
"Programming Language :: Python :: 3",
|
15
|
+
"Programming Language :: Python :: 3.10",
|
15
16
|
"Programming Language :: Python :: 3.11",
|
16
17
|
"Programming Language :: Python :: 3.12",
|
17
18
|
"Programming Language :: Python :: 3.13",
|
@@ -0,0 +1,8 @@
|
|
1
|
+
{
|
2
|
+
"ci_pipeline_created_at": "2025-06-27T15:27:06Z",
|
3
|
+
"ci_pipeline_id": "1894255377",
|
4
|
+
"ci_pipeline_url": "https://gitlab.com/blackstream-x/infdate/-/pipelines/1894255377",
|
5
|
+
"ci_project_title": "infdate",
|
6
|
+
"ci_project_url": "https://gitlab.com/blackstream-x/infdate",
|
7
|
+
"ci_commit_sha": "80b8357d36a7b921e46ce45b5c82298080b08b5f"
|
8
|
+
}
|
@@ -4,6 +4,6 @@ _provided by [glsr-present](https://pypi.org/project/glsr-present/) 0.3.6_
|
|
4
4
|
|
5
5
|
[infdate](https://gitlab.com/blackstream-x/infdate)
|
6
6
|
built with pipeline
|
7
|
-
[
|
8
|
-
(build started 2025-06-
|
7
|
+
[1894255377](https://gitlab.com/blackstream-x/infdate/-/pipelines/1894255377)
|
8
|
+
(build started 2025-06-27T15:27:06Z)
|
9
9
|
|
@@ -0,0 +1 @@
|
|
1
|
+
<?xml version="1.0" encoding="utf-8"?><testsuites name="pytest tests"><testsuite name="pytest" errors="0" failures="0" skipped="0" tests="39" time="1.137" timestamp="2025-06-27T15:27:43.088896+00:00" hostname="runner-xxurkrix-project-71015407-concurrent-0"><testcase classname="tests.test_infdate.GenericDateBase" name="test_bool" time="0.003" /><testcase classname="tests.test_infdate.GenericDateBase" name="test_eq" time="0.001" /><testcase classname="tests.test_infdate.GenericDateBase" name="test_ge" time="0.058" /><testcase classname="tests.test_infdate.GenericDateBase" name="test_gt" time="0.046" /><testcase classname="tests.test_infdate.GenericDateBase" name="test_hash" time="0.001" /><testcase classname="tests.test_infdate.GenericDateBase" name="test_isoformat" time="0.002" /><testcase classname="tests.test_infdate.GenericDateBase" name="test_le" time="0.057" /><testcase classname="tests.test_infdate.GenericDateBase" name="test_lt" time="0.047" /><testcase classname="tests.test_infdate.GenericDateBase" name="test_nan_not_allowed" time="0.002" /><testcase classname="tests.test_infdate.GenericDateBase" name="test_ne" time="0.047" /><testcase classname="tests.test_infdate.GenericDateBase" name="test_replace" time="0.001" /><testcase classname="tests.test_infdate.GenericDateBase" name="test_repr" time="0.001" /><testcase classname="tests.test_infdate.GenericDateBase" name="test_str" time="0.002" /><testcase classname="tests.test_infdate.GenericDateBase" name="test_strftime" time="0.001" /><testcase classname="tests.test_infdate.GenericDateBase" name="test_toordinal" time="0.001" /><testcase classname="tests.test_infdate.GenericDateArithmetics" name="test_add_and_radd" time="0.008" /><testcase classname="tests.test_infdate.GenericDateArithmetics" name="test_add_days" time="0.005" /><testcase classname="tests.test_infdate.GenericDateArithmetics" name="test_rsub_stdlib_date" time="0.001" /><testcase classname="tests.test_infdate.GenericDateArithmetics" name="test_sub_date" time="0.001" /><testcase classname="tests.test_infdate.GenericDateArithmetics" name="test_sub_number" time="0.005" /><testcase classname="tests.test_infdate.GenericDateArithmetics" name="test_sub_stdlib_date" time="0.001" /><testcase classname="tests.test_infdate.InfinityDate" name="test_replace" time="0.002" /><testcase classname="tests.test_infdate.InfinityDate" name="test_repr" time="0.001" /><testcase classname="tests.test_infdate.InfinityDate" name="test_strftime" time="0.001" /><testcase classname="tests.test_infdate.RealDate" name="test_attributes" time="0.001" /><testcase classname="tests.test_infdate.RealDate" name="test_bool" time="0.001" /><testcase classname="tests.test_infdate.RealDate" name="test_proxied_methods" time="0.002" /><testcase classname="tests.test_infdate.RealDate" name="test_random_date_within_limits" time="0.295" /><testcase classname="tests.test_infdate.RealDate" name="test_replace" time="0.002" /><testcase classname="tests.test_infdate.RealDate" name="test_repr" time="0.001" /><testcase classname="tests.test_infdate.RealDate" name="test_strftime" time="0.003" /><testcase classname="tests.test_infdate.FactoryFunctions" name="test_from_datetime_object" time="0.002" /><testcase classname="tests.test_infdate.FactoryFunctions" name="test_from_native_type" time="0.006" /><testcase classname="tests.test_infdate.FactoryFunctions" name="test_fromisocalendar" time="0.002" /><testcase classname="tests.test_infdate.FactoryFunctions" name="test_fromisoformat" time="0.002" /><testcase classname="tests.test_infdate.FactoryFunctions" name="test_fromordinal" time="0.003" /><testcase classname="tests.test_infdate.FactoryFunctions" name="test_fromtimestamp" time="0.003" /><testcase classname="tests.test_infdate.FactoryFunctions" name="test_fromtimestamp_errors" time="0.001" /><testcase classname="tests.test_infdate.FactoryFunctions" name="test_today" time="0.003" /></testsuite></testsuites>
|
@@ -6,7 +6,7 @@ capable of representing positive and negative infinity
|
|
6
6
|
"""
|
7
7
|
|
8
8
|
from datetime import date, datetime
|
9
|
-
from math import inf
|
9
|
+
from math import inf, trunc
|
10
10
|
from typing import final, overload, Any, Final, TypeVar
|
11
11
|
|
12
12
|
|
@@ -28,6 +28,8 @@ ISO_DATETIME_FORMAT_UTC: Final[str] = f"{ISO_DATE_FORMAT}T%H:%M:%S.%fZ"
|
|
28
28
|
MIN_ORDINAL: Final[int] = date.min.toordinal()
|
29
29
|
MAX_ORDINAL: Final[int] = date.max.toordinal()
|
30
30
|
|
31
|
+
RESOLUTION: Final[int] = 1
|
32
|
+
|
31
33
|
|
32
34
|
# -----------------------------------------------------------------------------
|
33
35
|
# Internal module constants:
|
@@ -45,15 +47,15 @@ _GD = TypeVar("_GD", bound="GenericDate")
|
|
45
47
|
class GenericDate:
|
46
48
|
"""Base Date object derived from an ordinal"""
|
47
49
|
|
48
|
-
|
49
|
-
resolution: Final = 1
|
50
|
-
# pylint: enable=invalid-name
|
51
|
-
|
52
|
-
def __init__(self, ordinal: float, /) -> None:
|
50
|
+
def __init__(self, ordinal: int | float, /) -> None:
|
53
51
|
"""Create a date-like object"""
|
54
|
-
|
52
|
+
if ordinal in (-inf, inf):
|
53
|
+
self.__ordinal = ordinal
|
54
|
+
else:
|
55
|
+
self.__ordinal = trunc(ordinal)
|
56
|
+
#
|
55
57
|
|
56
|
-
def toordinal(self: _GD) -> float:
|
58
|
+
def toordinal(self: _GD) -> int | float:
|
57
59
|
"""to ordinal (almost like date.toordinal())"""
|
58
60
|
return self.__ordinal
|
59
61
|
|
@@ -109,24 +111,30 @@ class GenericDate:
|
|
109
111
|
return self
|
110
112
|
#
|
111
113
|
# Return a RealDate instance if possible
|
112
|
-
return fromordinal(self.__ordinal + delta)
|
114
|
+
return fromordinal(self.__ordinal + trunc(delta))
|
113
115
|
|
114
116
|
def __add__(self: _GD, delta: int | float, /) -> _GD:
|
115
117
|
"""gd_instance1 + number capability"""
|
116
118
|
return self._add_days(delta)
|
117
119
|
|
120
|
+
__radd__ = __add__
|
121
|
+
|
118
122
|
@overload
|
119
123
|
def __sub__(self: _GD, other: int | float, /) -> _GD: ...
|
120
124
|
@overload
|
121
|
-
def __sub__(self: _GD, other: _GD, /) -> int | float: ...
|
125
|
+
def __sub__(self: _GD, other: _GD | date, /) -> int | float: ...
|
122
126
|
@final
|
123
|
-
def __sub__(self: _GD, other: _GD | int | float, /) -> _GD | int | float:
|
127
|
+
def __sub__(self: _GD, other: _GD | date | int | float, /) -> _GD | int | float:
|
124
128
|
"""subtract other, respecting possibly nondeterministic values"""
|
125
129
|
if isinstance(other, (int, float)):
|
126
130
|
return self._add_days(-other)
|
127
131
|
#
|
128
132
|
return self.__ordinal - other.toordinal()
|
129
133
|
|
134
|
+
def __rsub__(self: _GD, other: _GD | date, /) -> int | float:
|
135
|
+
"""subtract from other, respecting possibly nondeterministic values"""
|
136
|
+
return other.toordinal() - self.__ordinal
|
137
|
+
|
130
138
|
def __repr__(self: _GD, /) -> str:
|
131
139
|
"""String representation of the object"""
|
132
140
|
return f"{self.__class__.__name__}({repr(self.__ordinal)})"
|
@@ -186,7 +194,7 @@ class RealDate(GenericDate):
|
|
186
194
|
self.year = year
|
187
195
|
self.month = month
|
188
196
|
self.day = day
|
189
|
-
super().__init__(
|
197
|
+
super().__init__(self._wrapped_date_object.toordinal())
|
190
198
|
self.timetuple = self._wrapped_date_object.timetuple
|
191
199
|
self.weekday = self._wrapped_date_object.weekday
|
192
200
|
self.isoweekday = self._wrapped_date_object.isoweekday
|
@@ -274,7 +282,7 @@ def fromtimestamp(timestamp: float) -> GenericDate:
|
|
274
282
|
return from_datetime_object(stdlib_date_object)
|
275
283
|
|
276
284
|
|
277
|
-
def fromordinal(ordinal:
|
285
|
+
def fromordinal(ordinal: int | float) -> GenericDate:
|
278
286
|
"""Create an InfinityDate or RealDate instance from the provided ordinal"""
|
279
287
|
if ordinal == -inf:
|
280
288
|
return MIN
|
@@ -282,11 +290,7 @@ def fromordinal(ordinal: float | int) -> GenericDate:
|
|
282
290
|
if ordinal == inf:
|
283
291
|
return MAX
|
284
292
|
#
|
285
|
-
|
286
|
-
new_ordinal = int(ordinal)
|
287
|
-
except ValueError as error:
|
288
|
-
raise ValueError(f"Cannot convert {ordinal!r} to integer") from error
|
289
|
-
#
|
293
|
+
new_ordinal = trunc(ordinal)
|
290
294
|
if not MIN_ORDINAL <= new_ordinal <= MAX_ORDINAL:
|
291
295
|
raise OverflowError("RealDate value out of range")
|
292
296
|
#
|
@@ -18,6 +18,9 @@ import infdate
|
|
18
18
|
|
19
19
|
MAX_ORDINAL = datetime.date.max.toordinal()
|
20
20
|
|
21
|
+
# This is an error message from Python itself
|
22
|
+
_NAN_INT_CONVERSION_ERROR_RE = "^cannot convert float NaN to integer$"
|
23
|
+
|
21
24
|
|
22
25
|
def random_deterministic_date() -> infdate.GenericDate:
|
23
26
|
"""Helper function: create a random deterministic Date"""
|
@@ -32,14 +35,20 @@ class VerboseTestCase(unittest.TestCase):
|
|
32
35
|
self.maxDiff = None # pylint: disable=invalid-name ; name from unittest module
|
33
36
|
|
34
37
|
|
35
|
-
class
|
36
|
-
"""GenericDate objects"""
|
38
|
+
class GenericDateBase(VerboseTestCase):
|
39
|
+
"""GenericDate objects - base functionality"""
|
40
|
+
|
41
|
+
def test_nan_not_allowed(self):
|
42
|
+
"""test initialization with nan"""
|
43
|
+
self.assertRaisesRegex(
|
44
|
+
ValueError, _NAN_INT_CONVERSION_ERROR_RE, infdate.GenericDate, nan
|
45
|
+
)
|
37
46
|
|
38
47
|
def test_toordinal(self):
|
39
48
|
"""initialization and .toordinal() method"""
|
40
49
|
num = 1.23
|
41
50
|
gd = infdate.GenericDate(num)
|
42
|
-
self.assertEqual(gd.toordinal(),
|
51
|
+
self.assertEqual(gd.toordinal(), 1)
|
43
52
|
|
44
53
|
# pylint: disable=comparison-with-itself ; to show lt/gt ↔ le/ge difference
|
45
54
|
|
@@ -174,6 +183,8 @@ class GenericDate(VerboseTestCase):
|
|
174
183
|
self.assertTrue(random_date == random_date)
|
175
184
|
#
|
176
185
|
|
186
|
+
# pylint: enable=comparison-with-itself
|
187
|
+
|
177
188
|
def test_bool(self):
|
178
189
|
"""bool(gd_instance) capability"""
|
179
190
|
gd = infdate.GenericDate(3.579)
|
@@ -182,7 +193,61 @@ class GenericDate(VerboseTestCase):
|
|
182
193
|
def test_hash(self):
|
183
194
|
"""bool(gd_instance) capability"""
|
184
195
|
gd = infdate.GenericDate(0.5)
|
185
|
-
self.assertEqual(hash(gd), hash("date with ordinal 0
|
196
|
+
self.assertEqual(hash(gd), hash("date with ordinal 0"))
|
197
|
+
|
198
|
+
def test_repr(self):
|
199
|
+
"""repr(gd_instance) capability"""
|
200
|
+
for base, expected_display in (
|
201
|
+
(inf, "inf"),
|
202
|
+
(-inf, "-inf"),
|
203
|
+
(9.81, "9"),
|
204
|
+
(314, "314"),
|
205
|
+
):
|
206
|
+
gd = infdate.GenericDate(base)
|
207
|
+
with self.subTest(
|
208
|
+
"representation of",
|
209
|
+
base=base,
|
210
|
+
expected_display=expected_display,
|
211
|
+
):
|
212
|
+
self.assertEqual(repr(gd), f"GenericDate({expected_display})")
|
213
|
+
#
|
214
|
+
#
|
215
|
+
|
216
|
+
def test_str(self):
|
217
|
+
"""str(gd_instance) capability"""
|
218
|
+
gd = infdate.GenericDate(777)
|
219
|
+
mocked_isoformat_result = "[777]"
|
220
|
+
with patch.object(gd, "isoformat") as mock_isoformat:
|
221
|
+
mock_isoformat.return_value = mocked_isoformat_result
|
222
|
+
result = str(gd)
|
223
|
+
self.assertEqual(result, mocked_isoformat_result)
|
224
|
+
mock_isoformat.assert_called_with()
|
225
|
+
#
|
226
|
+
|
227
|
+
def test_isoformat(self):
|
228
|
+
""".isoformat() method"""
|
229
|
+
gd = infdate.GenericDate(777)
|
230
|
+
mocked_strftime_result = "[777]"
|
231
|
+
with patch.object(gd, "strftime") as mock_strftime:
|
232
|
+
mock_strftime.return_value = mocked_strftime_result
|
233
|
+
result = str(gd)
|
234
|
+
self.assertEqual(result, mocked_strftime_result)
|
235
|
+
mock_strftime.assert_called_with(infdate.ISO_DATE_FORMAT)
|
236
|
+
#
|
237
|
+
|
238
|
+
def test_strftime(self):
|
239
|
+
""".strftime() method"""
|
240
|
+
gd = infdate.GenericDate(-inf)
|
241
|
+
self.assertRaises(NotImplementedError, gd.strftime, "")
|
242
|
+
|
243
|
+
def test_replace(self):
|
244
|
+
""".replace() method"""
|
245
|
+
gd = infdate.GenericDate(inf)
|
246
|
+
self.assertRaises(NotImplementedError, gd.replace, year=1)
|
247
|
+
|
248
|
+
|
249
|
+
class GenericDateArithmetics(VerboseTestCase):
|
250
|
+
"""GenericDate objects - arithmetics"""
|
186
251
|
|
187
252
|
# pylint: disable=protected-access ; ok for testing
|
188
253
|
|
@@ -197,10 +262,10 @@ class GenericDate(VerboseTestCase):
|
|
197
262
|
(-inf, 77.98, -inf, None, True),
|
198
263
|
(9.81, inf, inf, inf, False),
|
199
264
|
(9.81, -inf, -inf, -inf, False),
|
200
|
-
(1.234, 7.89,
|
201
|
-
(7.62, 0, 7
|
202
|
-
(1.234, -5.678,
|
203
|
-
(3.14, -0
|
265
|
+
(1.234, 7.89, 8, 8, False),
|
266
|
+
(7.62, 0, 7, None, True),
|
267
|
+
(1.234, -5.678, -4, -4, False),
|
268
|
+
(3.14, -0, 3, None, True),
|
204
269
|
):
|
205
270
|
with patch.object(infdate, "fromordinal") as mock_fromordinal:
|
206
271
|
gd = infdate.GenericDate(base)
|
@@ -238,7 +303,7 @@ class GenericDate(VerboseTestCase):
|
|
238
303
|
#
|
239
304
|
#
|
240
305
|
|
241
|
-
def
|
306
|
+
def test_add_and_radd(self):
|
242
307
|
"""gd_instance + delta capability"""
|
243
308
|
for base, delta in (
|
244
309
|
(inf, inf),
|
@@ -258,9 +323,13 @@ class GenericDate(VerboseTestCase):
|
|
258
323
|
with patch.object(gd, "_add_days") as mock_adder:
|
259
324
|
_ = gd + delta
|
260
325
|
with self.subTest(
|
261
|
-
"._add_days() call
|
262
|
-
|
263
|
-
delta
|
326
|
+
f"GenericDate({base}) + {delta} → Gen…()._add_days({delta}) call"
|
327
|
+
):
|
328
|
+
mock_adder.assert_called_with(delta)
|
329
|
+
#
|
330
|
+
_ = delta + gd
|
331
|
+
with self.subTest(
|
332
|
+
f"{delta} + GenericDate({base}) → Gen…()._add_days({delta}) call"
|
264
333
|
):
|
265
334
|
mock_adder.assert_called_with(delta)
|
266
335
|
#
|
@@ -278,10 +347,10 @@ class GenericDate(VerboseTestCase):
|
|
278
347
|
(-inf, 77.98, -inf, None, True),
|
279
348
|
(9.81, -inf, inf, inf, False),
|
280
349
|
(9.81, inf, -inf, -inf, False),
|
281
|
-
(1.234, -7.89,
|
282
|
-
(7.62, -0, 7
|
283
|
-
(1.234, 5.678,
|
284
|
-
(3.14, 0.0, 3
|
350
|
+
(1.234, -7.89, 8, 7.89, False),
|
351
|
+
(7.62, -0, 7, None, True),
|
352
|
+
(1.234, 5.678, -4, -5.678, False),
|
353
|
+
(3.14, 0.0, 3, None, True),
|
285
354
|
):
|
286
355
|
gd = infdate.GenericDate(base)
|
287
356
|
with patch.object(gd, "_add_days") as mock_adder:
|
@@ -334,10 +403,10 @@ class GenericDate(VerboseTestCase):
|
|
334
403
|
(-inf, 77.98, -inf),
|
335
404
|
(9.81, -inf, inf),
|
336
405
|
(9.81, inf, -inf),
|
337
|
-
(1.234, -7.89,
|
338
|
-
(7.62, -0, 7
|
339
|
-
(1.234, 5.678,
|
340
|
-
(3.14, 0.0, 3
|
406
|
+
(1.234, -7.89, 8),
|
407
|
+
(7.62, -0, 7),
|
408
|
+
(1.234, 5.678, -4),
|
409
|
+
(3.14, 0.0, 3),
|
341
410
|
):
|
342
411
|
gd1 = infdate.GenericDate(first)
|
343
412
|
gd2 = infdate.GenericDate(second)
|
@@ -356,57 +425,51 @@ class GenericDate(VerboseTestCase):
|
|
356
425
|
#
|
357
426
|
#
|
358
427
|
|
359
|
-
def
|
360
|
-
"""
|
361
|
-
for
|
362
|
-
(inf,
|
363
|
-
(-inf,
|
364
|
-
(
|
365
|
-
(
|
366
|
-
(
|
428
|
+
def test_sub_stdlib_date(self):
|
429
|
+
"""gd_instance - stdlib_date capability"""
|
430
|
+
for gd_ordinal, stdlib_date_ordinal, expected_result in (
|
431
|
+
(inf, 981, inf),
|
432
|
+
(-inf, 733981, -inf),
|
433
|
+
(12, 1234, -1222),
|
434
|
+
(762, 1, 761),
|
435
|
+
(99999.99, 7777, 92222),
|
367
436
|
):
|
368
|
-
|
437
|
+
gd_instance = infdate.GenericDate(gd_ordinal)
|
438
|
+
stdlib_date = datetime.date.fromordinal(stdlib_date_ordinal)
|
439
|
+
result = gd_instance - stdlib_date
|
369
440
|
with self.subTest(
|
370
|
-
"
|
371
|
-
|
372
|
-
|
441
|
+
"result",
|
442
|
+
gd_ordinal=gd_ordinal,
|
443
|
+
stdlib_date_ordinal=stdlib_date_ordinal,
|
444
|
+
expected_result=expected_result,
|
373
445
|
):
|
374
|
-
self.assertEqual(
|
446
|
+
self.assertEqual(result, expected_result)
|
375
447
|
#
|
376
448
|
#
|
377
449
|
|
378
|
-
def
|
379
|
-
"""
|
380
|
-
|
381
|
-
|
382
|
-
|
383
|
-
|
384
|
-
|
385
|
-
|
386
|
-
|
387
|
-
|
388
|
-
|
389
|
-
|
390
|
-
|
391
|
-
|
392
|
-
|
393
|
-
|
394
|
-
|
395
|
-
|
396
|
-
|
397
|
-
|
450
|
+
def test_rsub_stdlib_date(self):
|
451
|
+
"""stdlib_date - gd_instance capability"""
|
452
|
+
for stdlib_date_ordinal, gd_ordinal, expected_result in (
|
453
|
+
(981, -inf, inf),
|
454
|
+
(981, inf, -inf),
|
455
|
+
(1234, -7.89, 1241),
|
456
|
+
(762, -0, 762),
|
457
|
+
(1234, 5.678, 1229),
|
458
|
+
(314, 0.0, 314),
|
459
|
+
):
|
460
|
+
stdlib_date = datetime.date.fromordinal(stdlib_date_ordinal)
|
461
|
+
gd_instance = infdate.GenericDate(gd_ordinal)
|
462
|
+
result = stdlib_date - gd_instance
|
463
|
+
with self.subTest(
|
464
|
+
"result",
|
465
|
+
stdlib_date_ordinal=stdlib_date_ordinal,
|
466
|
+
gd_ordinal=gd_ordinal,
|
467
|
+
expected_result=expected_result,
|
468
|
+
):
|
469
|
+
self.assertEqual(result, expected_result)
|
470
|
+
#
|
398
471
|
#
|
399
472
|
|
400
|
-
def test_strftime(self):
|
401
|
-
""".strftime() method"""
|
402
|
-
gd = infdate.GenericDate(-inf)
|
403
|
-
self.assertRaises(NotImplementedError, gd.strftime, "")
|
404
|
-
|
405
|
-
def test_replace(self):
|
406
|
-
""".replace() method"""
|
407
|
-
gd = infdate.GenericDate(inf)
|
408
|
-
self.assertRaises(NotImplementedError, gd.replace, year=1)
|
409
|
-
|
410
473
|
|
411
474
|
class InfinityDate(VerboseTestCase):
|
412
475
|
"""InfinityDate class"""
|
@@ -606,6 +669,27 @@ class RealDate(VerboseTestCase):
|
|
606
669
|
#
|
607
670
|
#
|
608
671
|
|
672
|
+
def test_random_date_within_limits(self):
|
673
|
+
"""The following relation
|
674
|
+
infdate.MIN < infdate.REAL_MIN <= real_date_instance <= …
|
675
|
+
… infdate.REAL_MAX < infdate.MAX
|
676
|
+
should always be True
|
677
|
+
"""
|
678
|
+
for iteration in range(1, 10000):
|
679
|
+
random_date = random_deterministic_date()
|
680
|
+
with self.subTest(
|
681
|
+
"date within limits", iteration=iteration, random_date=random_date
|
682
|
+
):
|
683
|
+
self.assertTrue(
|
684
|
+
infdate.MIN
|
685
|
+
< infdate.REAL_MIN
|
686
|
+
<= random_date
|
687
|
+
<= infdate.REAL_MAX
|
688
|
+
< infdate.MAX
|
689
|
+
)
|
690
|
+
#
|
691
|
+
#
|
692
|
+
|
609
693
|
|
610
694
|
class FactoryFunctions(VerboseTestCase):
|
611
695
|
"""Factory functions in the module"""
|
@@ -770,7 +854,7 @@ class FactoryFunctions(VerboseTestCase):
|
|
770
854
|
(-1, OverflowError, default_overflow_re),
|
771
855
|
(0, OverflowError, default_overflow_re),
|
772
856
|
(1234567890, OverflowError, default_overflow_re),
|
773
|
-
(nan, ValueError,
|
857
|
+
(nan, ValueError, _NAN_INT_CONVERSION_ERROR_RE),
|
774
858
|
):
|
775
859
|
with self.subTest("overflow error", ordinal=ordinal):
|
776
860
|
self.assertRaisesRegex(
|
@@ -1,8 +0,0 @@
|
|
1
|
-
{
|
2
|
-
"ci_pipeline_created_at": "2025-06-26T07:29:16Z",
|
3
|
-
"ci_pipeline_id": "1890497916",
|
4
|
-
"ci_pipeline_url": "https://gitlab.com/blackstream-x/infdate/-/pipelines/1890497916",
|
5
|
-
"ci_project_title": "infdate",
|
6
|
-
"ci_project_url": "https://gitlab.com/blackstream-x/infdate",
|
7
|
-
"ci_commit_sha": "7fd06146e7f50df22dc97ddaa53005459d17a1d4"
|
8
|
-
}
|
@@ -1 +0,0 @@
|
|
1
|
-
<?xml version="1.0" encoding="utf-8"?><testsuites name="pytest tests"><testsuite name="pytest" errors="0" failures="0" skipped="0" tests="35" time="0.784" timestamp="2025-06-26T07:29:48.605912+00:00" hostname="runner-nn8vmrs9z-project-71015407-concurrent-0"><testcase classname="tests.test_infdate.GenericDate" name="test_add" time="0.009" /><testcase classname="tests.test_infdate.GenericDate" name="test_add_days" time="0.005" /><testcase classname="tests.test_infdate.GenericDate" name="test_bool" time="0.001" /><testcase classname="tests.test_infdate.GenericDate" name="test_eq" time="0.001" /><testcase classname="tests.test_infdate.GenericDate" name="test_ge" time="0.056" /><testcase classname="tests.test_infdate.GenericDate" name="test_gt" time="0.047" /><testcase classname="tests.test_infdate.GenericDate" name="test_hash" time="0.001" /><testcase classname="tests.test_infdate.GenericDate" name="test_isoformat" time="0.001" /><testcase classname="tests.test_infdate.GenericDate" name="test_le" time="0.056" /><testcase classname="tests.test_infdate.GenericDate" name="test_lt" time="0.046" /><testcase classname="tests.test_infdate.GenericDate" name="test_ne" time="0.046" /><testcase classname="tests.test_infdate.GenericDate" name="test_replace" time="0.001" /><testcase classname="tests.test_infdate.GenericDate" name="test_repr" time="0.001" /><testcase classname="tests.test_infdate.GenericDate" name="test_str" time="0.001" /><testcase classname="tests.test_infdate.GenericDate" name="test_strftime" time="0.001" /><testcase classname="tests.test_infdate.GenericDate" name="test_sub_date" time="0.001" /><testcase classname="tests.test_infdate.GenericDate" name="test_sub_number" time="0.004" /><testcase classname="tests.test_infdate.GenericDate" name="test_toordinal" time="0.001" /><testcase classname="tests.test_infdate.InfinityDate" name="test_replace" time="0.001" /><testcase classname="tests.test_infdate.InfinityDate" name="test_repr" time="0.001" /><testcase classname="tests.test_infdate.InfinityDate" name="test_strftime" time="0.001" /><testcase classname="tests.test_infdate.RealDate" name="test_attributes" time="0.002" /><testcase classname="tests.test_infdate.RealDate" name="test_bool" time="0.001" /><testcase classname="tests.test_infdate.RealDate" name="test_proxied_methods" time="0.001" /><testcase classname="tests.test_infdate.RealDate" name="test_replace" time="0.002" /><testcase classname="tests.test_infdate.RealDate" name="test_repr" time="0.001" /><testcase classname="tests.test_infdate.RealDate" name="test_strftime" time="0.003" /><testcase classname="tests.test_infdate.FactoryFunctions" name="test_from_datetime_object" time="0.002" /><testcase classname="tests.test_infdate.FactoryFunctions" name="test_from_native_type" time="0.006" /><testcase classname="tests.test_infdate.FactoryFunctions" name="test_fromisocalendar" time="0.002" /><testcase classname="tests.test_infdate.FactoryFunctions" name="test_fromisoformat" time="0.002" /><testcase classname="tests.test_infdate.FactoryFunctions" name="test_fromordinal" time="0.003" /><testcase classname="tests.test_infdate.FactoryFunctions" name="test_fromtimestamp" time="0.003" /><testcase classname="tests.test_infdate.FactoryFunctions" name="test_fromtimestamp_errors" time="0.001" /><testcase classname="tests.test_infdate.FactoryFunctions" name="test_today" time="0.002" /></testsuite></testsuites>
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|