ics-query 0.1.1a0__tar.gz → 0.2.0a0__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.
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/PKG-INFO +54 -12
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/README.md +50 -8
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/_version.py +2 -2
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/cli.py +222 -7
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/parse.py +26 -4
- ics_query-0.2.0a0/ics_query/tests/runs/between 20240823 4d recurring-work-events.ics -.run +24 -0
- ics_query-0.2.0a0/ics_query/tests/runs/calendars/empty-calendar.ics +7 -0
- ics_query-0.2.0a0/ics_query/tests/runs/calendars/empty-file.ics +0 -0
- ics_query-0.2.0a0/ics_query/tests/runs/calendars/recurring-work-events.ics +223 -0
- ics_query-0.2.0a0/ics_query/tests/runs/first empty-calendar.ics -.run +0 -0
- ics_query-0.2.0a0/ics_query/tests/runs/first empty-file.ics -.run +0 -0
- ics_query-0.2.0a0/ics_query/tests/runs/first recurring-work-events.ics -.run +12 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/tests/test_parse_date.py +8 -5
- ics_query-0.2.0a0/ics_query/tests/test_parse_timedelta.py +25 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/pyproject.toml +2 -2
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/tox.ini +3 -1
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/.github/FUNDING.yml +0 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/.github/ISSUE_TEMPLATE/bug_report.md +0 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/.github/dependabot.yml +0 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/.github/workflows/tests.yml +0 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/.gitignore +0 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/LICENSE +0 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics-query +0 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/__init__.py +0 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/__main__.py +0 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/tests/__init__.py +0 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/tests/conftest.py +0 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/tests/runs/at 2019-03-04 multiple-calendars.ics -.run +0 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/tests/runs/at 2019-03-04 one-event-twice.ics -.run +0 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/tests/runs/at 2019-03-04 one-event.ics -.run +0 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/tests/runs/at 2019-03-07 multiple-calendars.ics -.run +0 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/tests/runs/calendars/multiple-calendars.ics +0 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/tests/runs/calendars/one-event-twice.ics +0 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/tests/runs/calendars/one-event.ics +0 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/tests/test_command_line.py +0 -0
- {ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/version.py +0 -0
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: ics-query
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.2.0a0
|
|
4
4
|
Summary: Find out what happens in ICS calendar files - query and filter RFC 5545 compatible .ics files for events, journals, TODOs and more.
|
|
5
5
|
Project-URL: Homepage, https://github.com/niccokunzmann/ics-query/
|
|
6
6
|
Project-URL: Repository, https://github.com/niccokunzmann/ics-query/
|
|
7
|
-
Project-URL: source_archive, https://github.com/niccokunzmann/ics-query/archive/
|
|
7
|
+
Project-URL: source_archive, https://github.com/niccokunzmann/ics-query/archive/c7eeb503fae7da069308a27a37232be96851c3e5.zip
|
|
8
8
|
Project-URL: Issues, https://github.com/niccokunzmann/ics-query/issues
|
|
9
9
|
Project-URL: Documentation, https://github.com/niccokunzmann/ics-query/
|
|
10
10
|
Project-URL: Changelog, https://github.com/niccokunzmann/ics-query/#changelog
|
|
@@ -695,10 +695,10 @@ Classifier: Programming Language :: Python :: 3.10
|
|
|
695
695
|
Classifier: Programming Language :: Python :: 3.11
|
|
696
696
|
Classifier: Programming Language :: Python :: 3.12
|
|
697
697
|
Classifier: Topic :: Office/Business :: Scheduling
|
|
698
|
-
Requires-Python: >=3.
|
|
698
|
+
Requires-Python: >=3.9
|
|
699
699
|
Requires-Dist: click
|
|
700
700
|
Requires-Dist: icalendar
|
|
701
|
-
Requires-Dist: recurring-ical-events
|
|
701
|
+
Requires-Dist: recurring-ical-events<4,>=3.2.0
|
|
702
702
|
Provides-Extra: test
|
|
703
703
|
Requires-Dist: pytest; extra == 'test'
|
|
704
704
|
Description-Content-Type: text/markdown
|
|
@@ -780,8 +780,46 @@ ics-query at <date-time> calendar.ics -
|
|
|
780
780
|
Please see the command documentation for more help:
|
|
781
781
|
|
|
782
782
|
```shell
|
|
783
|
-
ics-query --help
|
|
784
783
|
ics-query at --help
|
|
784
|
+
ics-query --help
|
|
785
|
+
```
|
|
786
|
+
|
|
787
|
+
### Events within a Time Span
|
|
788
|
+
|
|
789
|
+
You can query which events happen between certain times:
|
|
790
|
+
|
|
791
|
+
```shell
|
|
792
|
+
ics-query between <start> <end> calendar.ics -
|
|
793
|
+
ics-query between <start> <duration> calendar.ics -
|
|
794
|
+
```
|
|
795
|
+
|
|
796
|
+
Please see the command documentation for more help:
|
|
797
|
+
|
|
798
|
+
```shell
|
|
799
|
+
ics-query between --help
|
|
800
|
+
ics-query --help
|
|
801
|
+
```
|
|
802
|
+
|
|
803
|
+
### Time Span Examples
|
|
804
|
+
|
|
805
|
+
This example returns the events within the next week:
|
|
806
|
+
|
|
807
|
+
```shell
|
|
808
|
+
ics-query between `date +%Y%m%d` +7d calendar.ics -
|
|
809
|
+
```
|
|
810
|
+
|
|
811
|
+
This example saves the events from the 1st of May 2024 to the 10th of June in
|
|
812
|
+
events.ics:
|
|
813
|
+
|
|
814
|
+
```shell
|
|
815
|
+
ics-query between 2024-5-1 2024-6-10 calendar.ics events.ics
|
|
816
|
+
```
|
|
817
|
+
|
|
818
|
+
In this example, you can check what is happening on New Years Eve 2025 around
|
|
819
|
+
midnight:
|
|
820
|
+
|
|
821
|
+
```shell
|
|
822
|
+
ics-query between 2025-12-31T21:00 +6h calendar.ics events.ics
|
|
785
823
|
```
|
|
786
824
|
|
|
787
825
|
## Vision
|
|
@@ -810,13 +848,10 @@ ics-query --components VTODO at 2029-12-24 calendar.ics
|
|
|
810
848
|
|
|
811
849
|
### `ics-query at` - time ranges
|
|
812
850
|
|
|
813
|
-
|
|
814
851
|
### `ics-query --output=count` - count occurrences
|
|
815
852
|
|
|
816
|
-
|
|
817
853
|
### `ics-query --output=ics` - use ics as output (default)
|
|
818
854
|
|
|
819
|
-
|
|
820
855
|
### `ics-query --select-index` - reduce output size
|
|
821
856
|
|
|
822
857
|
Examples: `0,2,4` `0-10`
|
|
@@ -832,10 +867,8 @@ ics-query between dt duration
|
|
|
832
867
|
|
|
833
868
|
### `ics-query --select-component` - filter for components
|
|
834
869
|
|
|
835
|
-
|
|
836
870
|
### `ics-query --select-uid` - filter by uid
|
|
837
871
|
|
|
838
|
-
|
|
839
872
|
## How to edit an event
|
|
840
873
|
|
|
841
874
|
To edit a component like an event, you can append it to the calendar and increase the sequence number.
|
|
@@ -920,7 +953,7 @@ Run this to format the code and show problems:
|
|
|
920
953
|
tox -e ruff
|
|
921
954
|
```
|
|
922
955
|
|
|
923
|
-
|
|
956
|
+
### New Release
|
|
924
957
|
|
|
925
958
|
To release new versions,
|
|
926
959
|
|
|
@@ -938,10 +971,15 @@ To release new versions,
|
|
|
938
971
|
|
|
939
972
|
## Changelog
|
|
940
973
|
|
|
974
|
+
- v0.2.0a
|
|
975
|
+
|
|
976
|
+
- Add `ics-query first <calendar> <output>` for earliest occurrences
|
|
977
|
+
- Add `ics-query between <span_start> <span_stop> <calendar> <output>` to query time ranges
|
|
978
|
+
|
|
941
979
|
- v0.1.1a
|
|
942
980
|
|
|
943
981
|
- Add `--version`
|
|
944
|
-
- Add `ics-query at <date>`
|
|
982
|
+
- Add `ics-query at <date> <calendar> <output>`
|
|
945
983
|
- Add support for multiple calendars in one input
|
|
946
984
|
|
|
947
985
|
- v0.1.0a
|
|
@@ -952,3 +990,7 @@ To release new versions,
|
|
|
952
990
|
- v0.0.1a
|
|
953
991
|
|
|
954
992
|
- first version
|
|
993
|
+
|
|
994
|
+
## Related Work
|
|
995
|
+
|
|
996
|
+
- [icalBuddy](https://hasseg.org/icalBuddy/)
|
|
@@ -75,8 +75,46 @@ ics-query at <date-time> calendar.ics -
|
|
|
75
75
|
Please see the command documentation for more help:
|
|
76
76
|
|
|
77
77
|
```shell
|
|
78
|
-
ics-query --help
|
|
79
78
|
ics-query at --help
|
|
79
|
+
ics-query --help
|
|
80
|
+
```
|
|
81
|
+
|
|
82
|
+
### Events within a Time Span
|
|
83
|
+
|
|
84
|
+
You can query which events happen between certain times:
|
|
85
|
+
|
|
86
|
+
```shell
|
|
87
|
+
ics-query between <start> <end> calendar.ics -
|
|
88
|
+
ics-query between <start> <duration> calendar.ics -
|
|
89
|
+
```
|
|
90
|
+
|
|
91
|
+
Please see the command documentation for more help:
|
|
92
|
+
|
|
93
|
+
```shell
|
|
94
|
+
ics-query between --help
|
|
95
|
+
ics-query --help
|
|
96
|
+
```
|
|
97
|
+
|
|
98
|
+
### Time Span Examples
|
|
99
|
+
|
|
100
|
+
This example returns the events within the next week:
|
|
101
|
+
|
|
102
|
+
```shell
|
|
103
|
+
ics-query between `date +%Y%m%d` +7d calendar.ics -
|
|
104
|
+
```
|
|
105
|
+
|
|
106
|
+
This example saves the events from the 1st of May 2024 to the 10th of June in
|
|
107
|
+
events.ics:
|
|
108
|
+
|
|
109
|
+
```shell
|
|
110
|
+
ics-query between 2024-5-1 2024-6-10 calendar.ics events.ics
|
|
111
|
+
```
|
|
112
|
+
|
|
113
|
+
In this example, you can check what is happening on New Years Eve 2025 around
|
|
114
|
+
midnight:
|
|
115
|
+
|
|
116
|
+
```shell
|
|
117
|
+
ics-query between 2025-12-31T21:00 +6h calendar.ics events.ics
|
|
80
118
|
```
|
|
81
119
|
|
|
82
120
|
## Vision
|
|
@@ -105,13 +143,10 @@ ics-query --components VTODO at 2029-12-24 calendar.ics
|
|
|
105
143
|
|
|
106
144
|
### `ics-query at` - time ranges
|
|
107
145
|
|
|
108
|
-
|
|
109
146
|
### `ics-query --output=count` - count occurrences
|
|
110
147
|
|
|
111
|
-
|
|
112
148
|
### `ics-query --output=ics` - use ics as output (default)
|
|
113
149
|
|
|
114
|
-
|
|
115
150
|
### `ics-query --select-index` - reduce output size
|
|
116
151
|
|
|
117
152
|
Examples: `0,2,4` `0-10`
|
|
@@ -127,10 +162,8 @@ ics-query between dt duration
|
|
|
127
162
|
|
|
128
163
|
### `ics-query --select-component` - filter for components
|
|
129
164
|
|
|
130
|
-
|
|
131
165
|
### `ics-query --select-uid` - filter by uid
|
|
132
166
|
|
|
133
|
-
|
|
134
167
|
## How to edit an event
|
|
135
168
|
|
|
136
169
|
To edit a component like an event, you can append it to the calendar and increase the sequence number.
|
|
@@ -215,7 +248,7 @@ Run this to format the code and show problems:
|
|
|
215
248
|
tox -e ruff
|
|
216
249
|
```
|
|
217
250
|
|
|
218
|
-
|
|
251
|
+
### New Release
|
|
219
252
|
|
|
220
253
|
To release new versions,
|
|
221
254
|
|
|
@@ -233,10 +266,15 @@ To release new versions,
|
|
|
233
266
|
|
|
234
267
|
## Changelog
|
|
235
268
|
|
|
269
|
+
- v0.2.0a
|
|
270
|
+
|
|
271
|
+
- Add `ics-query first <calendar> <output>` for earliest occurrences
|
|
272
|
+
- Add `ics-query between <span_start> <span_stop> <calendar> <output>` to query time ranges
|
|
273
|
+
|
|
236
274
|
- v0.1.1a
|
|
237
275
|
|
|
238
276
|
- Add `--version`
|
|
239
|
-
- Add `ics-query at <date>`
|
|
277
|
+
- Add `ics-query at <date> <calendar> <output>`
|
|
240
278
|
- Add support for multiple calendars in one input
|
|
241
279
|
|
|
242
280
|
- v0.1.0a
|
|
@@ -247,3 +285,7 @@ To release new versions,
|
|
|
247
285
|
- v0.0.1a
|
|
248
286
|
|
|
249
287
|
- first version
|
|
288
|
+
|
|
289
|
+
## Related Work
|
|
290
|
+
|
|
291
|
+
- [icalBuddy](https://hasseg.org/icalBuddy/)
|
|
@@ -10,7 +10,6 @@ import typing as t
|
|
|
10
10
|
import click
|
|
11
11
|
import recurring_ical_events
|
|
12
12
|
from icalendar.cal import Calendar, Component
|
|
13
|
-
from recurring_ical_events import CalendarQuery
|
|
14
13
|
|
|
15
14
|
from . import parse
|
|
16
15
|
from .version import __version__
|
|
@@ -20,7 +19,7 @@ if t.TYPE_CHECKING:
|
|
|
20
19
|
|
|
21
20
|
from icalendar.cal import Component
|
|
22
21
|
|
|
23
|
-
from .parse import
|
|
22
|
+
from .parse import Date
|
|
24
23
|
|
|
25
24
|
print = functools.partial(print, file=sys.stderr) # noqa: A001
|
|
26
25
|
|
|
@@ -36,6 +35,11 @@ class ComponentsResult:
|
|
|
36
35
|
"""Return a component."""
|
|
37
36
|
self._file.write(component.to_ical())
|
|
38
37
|
|
|
38
|
+
def add_components(self, components: t.Iterable[Component]):
|
|
39
|
+
"""Add all components."""
|
|
40
|
+
for component in components:
|
|
41
|
+
self.add_component(component)
|
|
42
|
+
|
|
39
43
|
|
|
40
44
|
class ComponentsResultArgument(click.File):
|
|
41
45
|
"""Argument for the result."""
|
|
@@ -61,6 +65,19 @@ class JoinedCalendars:
|
|
|
61
65
|
for query in self.queries:
|
|
62
66
|
yield from query.at(dt)
|
|
63
67
|
|
|
68
|
+
def first(self) -> t.Generator[Component]:
|
|
69
|
+
"""Return the first events of all calendars."""
|
|
70
|
+
for query in self.queries:
|
|
71
|
+
for component in query.all():
|
|
72
|
+
yield component
|
|
73
|
+
break
|
|
74
|
+
|
|
75
|
+
def between(
|
|
76
|
+
self, start: parse.Date, end: parse.DateAndDelta
|
|
77
|
+
) -> t.Generator[Component]:
|
|
78
|
+
for query in self.queries:
|
|
79
|
+
yield from query.between(start, end)
|
|
80
|
+
|
|
64
81
|
|
|
65
82
|
class CalendarQueryInputArgument(click.File):
|
|
66
83
|
"""Argument for the result."""
|
|
@@ -133,7 +150,7 @@ pass_datetime = click.make_pass_decorator(parse.to_time)
|
|
|
133
150
|
@click.argument("date", type=parse.to_time)
|
|
134
151
|
@arg_calendar
|
|
135
152
|
@arg_output
|
|
136
|
-
def at(calendar:
|
|
153
|
+
def at(calendar: JoinedCalendars, output: ComponentsResult, date: Date):
|
|
137
154
|
"""Occurrences at a certain dates.
|
|
138
155
|
|
|
139
156
|
YEAR
|
|
@@ -156,7 +173,7 @@ def at(calendar: CalendarQuery, output: ComponentsResult, date: DateArgument):
|
|
|
156
173
|
|
|
157
174
|
\b
|
|
158
175
|
Formats:
|
|
159
|
-
|
|
176
|
+
\b
|
|
160
177
|
YYYY-MM
|
|
161
178
|
YYYY-M
|
|
162
179
|
YYYYMM
|
|
@@ -175,7 +192,7 @@ def at(calendar: CalendarQuery, output: ComponentsResult, date: DateArgument):
|
|
|
175
192
|
|
|
176
193
|
\b
|
|
177
194
|
Formats:
|
|
178
|
-
|
|
195
|
+
\b
|
|
179
196
|
YYYY-MM-DD
|
|
180
197
|
YYYY-M-D
|
|
181
198
|
YYYYMMDD
|
|
@@ -253,8 +270,206 @@ def at(calendar: CalendarQuery, output: ComponentsResult, date: DateArgument):
|
|
|
253
270
|
ics-query at 19900101235959 # 1st January 1990, 23:59:59
|
|
254
271
|
ics-query at `date +%Y%m%d%H%M%S` # now
|
|
255
272
|
""" # noqa: D301
|
|
256
|
-
|
|
257
|
-
|
|
273
|
+
output.add_components(calendar.at(date))
|
|
274
|
+
|
|
275
|
+
|
|
276
|
+
@main.command()
|
|
277
|
+
@arg_calendar
|
|
278
|
+
@arg_output
|
|
279
|
+
def first(calendar: JoinedCalendars, output: ComponentsResult):
|
|
280
|
+
"""Print only the first occurrence in each calendar.
|
|
281
|
+
|
|
282
|
+
\b
|
|
283
|
+
This example prints the first event in calendar.ics:
|
|
284
|
+
\b
|
|
285
|
+
ics-query first calendar.ics -
|
|
286
|
+
|
|
287
|
+
""" # noqa: D301
|
|
288
|
+
output.add_components(calendar.first())
|
|
289
|
+
|
|
290
|
+
|
|
291
|
+
@main.command()
|
|
292
|
+
@click.argument("start", type=parse.to_time)
|
|
293
|
+
@click.argument("end", type=parse.to_time_and_delta)
|
|
294
|
+
@arg_calendar
|
|
295
|
+
@arg_output
|
|
296
|
+
def between(
|
|
297
|
+
start: parse.Date,
|
|
298
|
+
end: parse.DateAndDelta,
|
|
299
|
+
calendar: JoinedCalendars,
|
|
300
|
+
output: ComponentsResult,
|
|
301
|
+
):
|
|
302
|
+
"""Print all occurrences between the START and the END.
|
|
303
|
+
|
|
304
|
+
The start is inclusive, the end is exclusive.
|
|
305
|
+
|
|
306
|
+
This example returns the events within the next week:
|
|
307
|
+
|
|
308
|
+
\b
|
|
309
|
+
ics-query between `date +%Y%m%d` +7d calendar.ics -
|
|
310
|
+
|
|
311
|
+
This example saves the events from the 1st of May 2024 to the 10th of June in
|
|
312
|
+
events.ics:
|
|
313
|
+
|
|
314
|
+
\b
|
|
315
|
+
ics-query between 2024-5-1 2024-6-10 calendar.ics events.ics
|
|
316
|
+
|
|
317
|
+
In this example, you can check what is happening on New Years Eve 2025 around
|
|
318
|
+
midnight:
|
|
319
|
+
|
|
320
|
+
\b
|
|
321
|
+
ics-query between 2025-12-31T21:00 +6h calendar.ics events.ics
|
|
322
|
+
|
|
323
|
+
\b
|
|
324
|
+
Absolute Time
|
|
325
|
+
-------------
|
|
326
|
+
|
|
327
|
+
START must be specified as an absolute time.
|
|
328
|
+
END can be absolute or relative to START, see Relative Time below.
|
|
329
|
+
|
|
330
|
+
Each of the formats specify the earliest time e.g. the start of a day.
|
|
331
|
+
Thus, if START == END, there are 0 seconds in between and the result is
|
|
332
|
+
only what happens during that time or starts exactly at that time.
|
|
333
|
+
|
|
334
|
+
YEAR
|
|
335
|
+
|
|
336
|
+
Specifiy the start of the year.
|
|
337
|
+
|
|
338
|
+
\b
|
|
339
|
+
Formats:
|
|
340
|
+
\b
|
|
341
|
+
YYYY
|
|
342
|
+
\b
|
|
343
|
+
Examples:
|
|
344
|
+
\b
|
|
345
|
+
2024 # start of 2024
|
|
346
|
+
`date +%Y` # this year
|
|
347
|
+
|
|
348
|
+
MONTH
|
|
349
|
+
|
|
350
|
+
The start of the month.
|
|
351
|
+
|
|
352
|
+
\b
|
|
353
|
+
Formats:
|
|
354
|
+
\b
|
|
355
|
+
YYYY-MM
|
|
356
|
+
YYYY-M
|
|
357
|
+
YYYYMM
|
|
358
|
+
\b
|
|
359
|
+
Examples:
|
|
360
|
+
\b
|
|
361
|
+
2019-10 # October 2019
|
|
362
|
+
1990-01 # January 1990
|
|
363
|
+
1990-1 # January 1990
|
|
364
|
+
199001 # January 1990
|
|
365
|
+
`date +%Y%m` # this month
|
|
366
|
+
|
|
367
|
+
DAY
|
|
368
|
+
|
|
369
|
+
The start of the day
|
|
370
|
+
|
|
371
|
+
\b
|
|
372
|
+
Formats:
|
|
373
|
+
\b
|
|
374
|
+
YYYY-MM-DD
|
|
375
|
+
YYYY-M-D
|
|
376
|
+
YYYYMMDD
|
|
377
|
+
\b
|
|
378
|
+
Examples:
|
|
379
|
+
\b
|
|
380
|
+
1990-01-01 # 1st January 1990
|
|
381
|
+
1990-1-1 # 1st January 1990
|
|
382
|
+
19900101 # 1st January 1990
|
|
383
|
+
`date +%Y%m%d` # today
|
|
384
|
+
|
|
385
|
+
HOUR
|
|
386
|
+
|
|
387
|
+
The start of the hour.
|
|
388
|
+
|
|
389
|
+
\b
|
|
390
|
+
Formats:
|
|
391
|
+
\b
|
|
392
|
+
YYYY-MM-DD HH
|
|
393
|
+
YYYY-MM-DDTHH
|
|
394
|
+
YYYY-M-DTH
|
|
395
|
+
YYYYMMDDTHH
|
|
396
|
+
YYYYMMDDHH
|
|
397
|
+
\b
|
|
398
|
+
Examples:
|
|
399
|
+
\b
|
|
400
|
+
1990-01-01 01 # 1st January 1990, 1am
|
|
401
|
+
1990-01-01T01 # 1st January 1990, 1am
|
|
402
|
+
1990-1-1T17 # 1st January 1990, 17:00
|
|
403
|
+
19900101T23 # 1st January 1990, 23:00
|
|
404
|
+
1990010123 # 1st January 1990, 23:00
|
|
405
|
+
`date +%Y%m%d%H` # this hour
|
|
406
|
+
|
|
407
|
+
MINUTE
|
|
408
|
+
|
|
409
|
+
The start of a minute.
|
|
410
|
+
|
|
411
|
+
\b
|
|
412
|
+
Formats:
|
|
413
|
+
\b
|
|
414
|
+
YYYY-MM-DD HH:MM
|
|
415
|
+
YYYY-MM-DDTHH:MM
|
|
416
|
+
YYYY-M-DTH:M
|
|
417
|
+
YYYYMMDDTHHMM
|
|
418
|
+
YYYYMMDDHHMM
|
|
419
|
+
\b
|
|
420
|
+
Examples:
|
|
421
|
+
\b
|
|
422
|
+
1990-01-01 10:10 # 1st January 1990, 10:10am
|
|
423
|
+
1990-01-01T10:10 # 1st January 1990, 10:10am
|
|
424
|
+
1990-1-1T7:2 # 1st January 1990, 07:02
|
|
425
|
+
19900101T2359 # 1st January 1990, 23:59
|
|
426
|
+
199001012359 # 1st January 1990, 23:59
|
|
427
|
+
`date +%Y%m%d%H%M` # this minute
|
|
428
|
+
|
|
429
|
+
SECOND
|
|
430
|
+
|
|
431
|
+
A precise time. RFC 5545 calendars are specified to the second.
|
|
432
|
+
This is the most precise format to specify times.
|
|
433
|
+
|
|
434
|
+
\b
|
|
435
|
+
Formats:
|
|
436
|
+
\b
|
|
437
|
+
YYYY-MM-DD HH:MM:SS
|
|
438
|
+
YYYY-MM-DDTHH:MM:SS
|
|
439
|
+
YYYY-M-DTH:M:S
|
|
440
|
+
YYYYMMDDTHHMMSS
|
|
441
|
+
YYYYMMDDHHMMSS
|
|
442
|
+
\b
|
|
443
|
+
Examples:
|
|
444
|
+
\b
|
|
445
|
+
1990-01-01 10:10:00 # 1st January 1990, 10:10am
|
|
446
|
+
1990-01-01T10:10:00 # 1st January 1990, 10:10am
|
|
447
|
+
1990-1-1T7:2:30 # 1st January 1990, 07:02:30
|
|
448
|
+
19901231T235959 # 31st December 1990, 23:59:59
|
|
449
|
+
19900101235959 # 1st January 1990, 23:59:59
|
|
450
|
+
`date +%Y%m%d%H%M%S` # now
|
|
451
|
+
\b
|
|
452
|
+
Relative Time
|
|
453
|
+
-------------
|
|
454
|
+
|
|
455
|
+
The END argument can be a time range.
|
|
456
|
+
The + at the beginning is optional but makes for a better reading.
|
|
457
|
+
|
|
458
|
+
\b
|
|
459
|
+
Examples:
|
|
460
|
+
\b
|
|
461
|
+
Add 10 days to START: +10d
|
|
462
|
+
Add 24 hours to START: +1d or +24h
|
|
463
|
+
Add 3 hours to START: +3h
|
|
464
|
+
Add 30 minutes to START: +30m
|
|
465
|
+
Add 1000 seconds to START: +1000s
|
|
466
|
+
\b
|
|
467
|
+
You can also combine the ranges:
|
|
468
|
+
Add 1 day and 12 hours to START: +1d12h
|
|
469
|
+
Add 3 hours and 15 minutes to START: +3h15m
|
|
470
|
+
|
|
471
|
+
""" # noqa: D301
|
|
472
|
+
output.add_components(calendar.between(start, end))
|
|
258
473
|
|
|
259
474
|
|
|
260
475
|
__all__ = ["main"]
|
|
@@ -2,9 +2,12 @@
|
|
|
2
2
|
|
|
3
3
|
from __future__ import annotations
|
|
4
4
|
|
|
5
|
+
import datetime
|
|
5
6
|
import re
|
|
7
|
+
from typing import Union
|
|
6
8
|
|
|
7
|
-
|
|
9
|
+
Date = tuple[int]
|
|
10
|
+
DateAndDelta = Union[Date, datetime.timedelta]
|
|
8
11
|
|
|
9
12
|
|
|
10
13
|
class InvalidTimeFormat(ValueError):
|
|
@@ -21,14 +24,22 @@ REGEX_TIME = re.compile(
|
|
|
21
24
|
r"$"
|
|
22
25
|
)
|
|
23
26
|
|
|
27
|
+
REGEX_TIMEDELTA = re.compile(
|
|
28
|
+
r"^\+?(?:(?P<days>\d+)d)?"
|
|
29
|
+
r"(?:(?P<hours>\d+)h)?"
|
|
30
|
+
r"(?:(?P<minutes>\d+)m)?"
|
|
31
|
+
r"(?:(?P<seconds>\d+)s)?"
|
|
32
|
+
r"$"
|
|
33
|
+
)
|
|
34
|
+
|
|
24
35
|
|
|
25
|
-
def to_time(dt: str) ->
|
|
36
|
+
def to_time(dt: str) -> Date:
|
|
26
37
|
"""Parse the time and date."""
|
|
27
38
|
parsed_dt = REGEX_TIME.match(dt)
|
|
28
39
|
if parsed_dt is None:
|
|
29
40
|
raise InvalidTimeFormat(dt)
|
|
30
41
|
|
|
31
|
-
def group(group_name: str) ->
|
|
42
|
+
def group(group_name: str) -> Date:
|
|
32
43
|
"""Return a group's value."""
|
|
33
44
|
result = parsed_dt.group(group_name)
|
|
34
45
|
while result and result[0] not in "0123456789":
|
|
@@ -47,4 +58,15 @@ def to_time(dt: str) -> DateArgument:
|
|
|
47
58
|
)
|
|
48
59
|
|
|
49
60
|
|
|
50
|
-
|
|
61
|
+
def to_time_and_delta(dt: str) -> DateAndDelta:
|
|
62
|
+
"""Parse to a absolute time or timedelta."""
|
|
63
|
+
parsed_td = REGEX_TIMEDELTA.match(dt)
|
|
64
|
+
if parsed_td is None:
|
|
65
|
+
return to_time(dt)
|
|
66
|
+
kw = {k: int(v) for k, v in parsed_td.groupdict().items() if v is not None}
|
|
67
|
+
if not kw:
|
|
68
|
+
raise InvalidTimeFormat(dt)
|
|
69
|
+
return datetime.timedelta(**kw)
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
__all__ = ["to_time", "Date", "to_time_and_delta", "DateAndDelta"]
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
BEGIN:VEVENT
|
|
2
|
+
SUMMARY:Work
|
|
3
|
+
DTSTART;TZID=Europe/Berlin:20240823T090000
|
|
4
|
+
DTEND;TZID=Europe/Berlin:20240823T170000
|
|
5
|
+
DTSTAMP:20240823T082915Z
|
|
6
|
+
UID:6b85b60c-eb1a-4338-9ece-33541b95bf17
|
|
7
|
+
SEQUENCE:1
|
|
8
|
+
CREATED:20240823T082829Z
|
|
9
|
+
LAST-MODIFIED:20240823T082915Z
|
|
10
|
+
TRANSP:OPAQUE
|
|
11
|
+
X-MOZ-GENERATION:2
|
|
12
|
+
END:VEVENT
|
|
13
|
+
BEGIN:VEVENT
|
|
14
|
+
SUMMARY:Work
|
|
15
|
+
DTSTART;TZID=Europe/Berlin:20240826T090000
|
|
16
|
+
DTEND;TZID=Europe/Berlin:20240826T170000
|
|
17
|
+
DTSTAMP:20240823T082915Z
|
|
18
|
+
UID:6b85b60c-eb1a-4338-9ece-33541b95bf17
|
|
19
|
+
SEQUENCE:1
|
|
20
|
+
CREATED:20240823T082829Z
|
|
21
|
+
LAST-MODIFIED:20240823T082915Z
|
|
22
|
+
TRANSP:OPAQUE
|
|
23
|
+
X-MOZ-GENERATION:2
|
|
24
|
+
END:VEVENT
|
|
File without changes
|
|
@@ -0,0 +1,223 @@
|
|
|
1
|
+
BEGIN:VCALENDAR
|
|
2
|
+
PRODID:-//Mozilla.org/NONSGML Mozilla Calendar V1.1//EN
|
|
3
|
+
VERSION:2.0
|
|
4
|
+
BEGIN:VTIMEZONE
|
|
5
|
+
TZID:Europe/Berlin
|
|
6
|
+
X-TZINFO:Europe/Berlin[2024a]
|
|
7
|
+
BEGIN:STANDARD
|
|
8
|
+
TZOFFSETTO:+010000
|
|
9
|
+
TZOFFSETFROM:+005328
|
|
10
|
+
TZNAME:Europe/Berlin(STD)
|
|
11
|
+
DTSTART:18930401T000000
|
|
12
|
+
RDATE:18930401T000000
|
|
13
|
+
END:STANDARD
|
|
14
|
+
BEGIN:DAYLIGHT
|
|
15
|
+
TZOFFSETTO:+020000
|
|
16
|
+
TZOFFSETFROM:+010000
|
|
17
|
+
TZNAME:Europe/Berlin(DST)
|
|
18
|
+
DTSTART:19160430T230000
|
|
19
|
+
RDATE:19160430T230000
|
|
20
|
+
END:DAYLIGHT
|
|
21
|
+
BEGIN:STANDARD
|
|
22
|
+
TZOFFSETTO:+010000
|
|
23
|
+
TZOFFSETFROM:+020000
|
|
24
|
+
TZNAME:Europe/Berlin(STD)
|
|
25
|
+
DTSTART:19161001T010000
|
|
26
|
+
RDATE:19161001T010000
|
|
27
|
+
END:STANDARD
|
|
28
|
+
BEGIN:DAYLIGHT
|
|
29
|
+
TZOFFSETTO:+020000
|
|
30
|
+
TZOFFSETFROM:+010000
|
|
31
|
+
TZNAME:Europe/Berlin(DST)
|
|
32
|
+
DTSTART:19170416T020000
|
|
33
|
+
RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=3MO;UNTIL=19180415T020000
|
|
34
|
+
END:DAYLIGHT
|
|
35
|
+
BEGIN:STANDARD
|
|
36
|
+
TZOFFSETTO:+010000
|
|
37
|
+
TZOFFSETFROM:+020000
|
|
38
|
+
TZNAME:Europe/Berlin(STD)
|
|
39
|
+
DTSTART:19170917T030000
|
|
40
|
+
RRULE:FREQ=YEARLY;BYMONTH=9;BYDAY=3MO;UNTIL=19180916T030000
|
|
41
|
+
END:STANDARD
|
|
42
|
+
BEGIN:DAYLIGHT
|
|
43
|
+
TZOFFSETTO:+020000
|
|
44
|
+
TZOFFSETFROM:+010000
|
|
45
|
+
TZNAME:Europe/Berlin(DST)
|
|
46
|
+
DTSTART:19400401T020000
|
|
47
|
+
RDATE:19400401T020000
|
|
48
|
+
END:DAYLIGHT
|
|
49
|
+
BEGIN:STANDARD
|
|
50
|
+
TZOFFSETTO:+010000
|
|
51
|
+
TZOFFSETFROM:+020000
|
|
52
|
+
TZNAME:Europe/Berlin(STD)
|
|
53
|
+
DTSTART:19421102T030000
|
|
54
|
+
RDATE:19421102T030000
|
|
55
|
+
END:STANDARD
|
|
56
|
+
BEGIN:DAYLIGHT
|
|
57
|
+
TZOFFSETTO:+020000
|
|
58
|
+
TZOFFSETFROM:+010000
|
|
59
|
+
TZNAME:Europe/Berlin(DST)
|
|
60
|
+
DTSTART:19430329T020000
|
|
61
|
+
RDATE:19430329T020000
|
|
62
|
+
END:DAYLIGHT
|
|
63
|
+
BEGIN:DAYLIGHT
|
|
64
|
+
TZOFFSETTO:+020000
|
|
65
|
+
TZOFFSETFROM:+010000
|
|
66
|
+
TZNAME:Europe/Berlin(DST)
|
|
67
|
+
DTSTART:19440403T020000
|
|
68
|
+
RRULE:FREQ=YEARLY;BYMONTH=4;BYDAY=1MO;UNTIL=19450402T020000
|
|
69
|
+
END:DAYLIGHT
|
|
70
|
+
BEGIN:DAYLIGHT
|
|
71
|
+
TZOFFSETTO:+030000
|
|
72
|
+
TZOFFSETFROM:+020000
|
|
73
|
+
TZNAME:Europe/Berlin(DST)
|
|
74
|
+
DTSTART:19450524T020000
|
|
75
|
+
RDATE:19450524T020000
|
|
76
|
+
END:DAYLIGHT
|
|
77
|
+
BEGIN:STANDARD
|
|
78
|
+
TZOFFSETTO:+010000
|
|
79
|
+
TZOFFSETFROM:+020000
|
|
80
|
+
TZNAME:Europe/Berlin(STD)
|
|
81
|
+
DTSTART:19431004T030000
|
|
82
|
+
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=1MO;UNTIL=19441002T030000
|
|
83
|
+
END:STANDARD
|
|
84
|
+
BEGIN:DAYLIGHT
|
|
85
|
+
TZOFFSETTO:+020000
|
|
86
|
+
TZOFFSETFROM:+030000
|
|
87
|
+
TZNAME:Europe/Berlin(DST)
|
|
88
|
+
DTSTART:19450924T030000
|
|
89
|
+
RDATE:19450924T030000
|
|
90
|
+
END:DAYLIGHT
|
|
91
|
+
BEGIN:STANDARD
|
|
92
|
+
TZOFFSETTO:+010000
|
|
93
|
+
TZOFFSETFROM:+020000
|
|
94
|
+
TZNAME:Europe/Berlin(STD)
|
|
95
|
+
DTSTART:19451118T030000
|
|
96
|
+
RDATE:19451118T030000
|
|
97
|
+
END:STANDARD
|
|
98
|
+
BEGIN:DAYLIGHT
|
|
99
|
+
TZOFFSETTO:+020000
|
|
100
|
+
TZOFFSETFROM:+010000
|
|
101
|
+
TZNAME:Europe/Berlin(DST)
|
|
102
|
+
DTSTART:19460414T020000
|
|
103
|
+
RDATE:19460414T020000
|
|
104
|
+
END:DAYLIGHT
|
|
105
|
+
BEGIN:DAYLIGHT
|
|
106
|
+
TZOFFSETTO:+020000
|
|
107
|
+
TZOFFSETFROM:+010000
|
|
108
|
+
TZNAME:Europe/Berlin(DST)
|
|
109
|
+
DTSTART:19470406T030000
|
|
110
|
+
RDATE:19470406T030000
|
|
111
|
+
END:DAYLIGHT
|
|
112
|
+
BEGIN:DAYLIGHT
|
|
113
|
+
TZOFFSETTO:+030000
|
|
114
|
+
TZOFFSETFROM:+020000
|
|
115
|
+
TZNAME:Europe/Berlin(DST)
|
|
116
|
+
DTSTART:19470511T030000
|
|
117
|
+
RDATE:19470511T030000
|
|
118
|
+
END:DAYLIGHT
|
|
119
|
+
BEGIN:STANDARD
|
|
120
|
+
TZOFFSETTO:+010000
|
|
121
|
+
TZOFFSETFROM:+020000
|
|
122
|
+
TZNAME:Europe/Berlin(STD)
|
|
123
|
+
DTSTART:19461007T030000
|
|
124
|
+
RDATE:19461007T030000
|
|
125
|
+
END:STANDARD
|
|
126
|
+
BEGIN:DAYLIGHT
|
|
127
|
+
TZOFFSETTO:+020000
|
|
128
|
+
TZOFFSETFROM:+030000
|
|
129
|
+
TZNAME:Europe/Berlin(DST)
|
|
130
|
+
DTSTART:19470629T030000
|
|
131
|
+
RDATE:19470629T030000
|
|
132
|
+
END:DAYLIGHT
|
|
133
|
+
BEGIN:DAYLIGHT
|
|
134
|
+
TZOFFSETTO:+020000
|
|
135
|
+
TZOFFSETFROM:+010000
|
|
136
|
+
TZNAME:Europe/Berlin(DST)
|
|
137
|
+
DTSTART:19480418T020000
|
|
138
|
+
RDATE:19480418T020000
|
|
139
|
+
END:DAYLIGHT
|
|
140
|
+
BEGIN:DAYLIGHT
|
|
141
|
+
TZOFFSETTO:+020000
|
|
142
|
+
TZOFFSETFROM:+010000
|
|
143
|
+
TZNAME:Europe/Berlin(DST)
|
|
144
|
+
DTSTART:19490410T020000
|
|
145
|
+
RDATE:19490410T020000
|
|
146
|
+
END:DAYLIGHT
|
|
147
|
+
BEGIN:STANDARD
|
|
148
|
+
TZOFFSETTO:+010000
|
|
149
|
+
TZOFFSETFROM:+020000
|
|
150
|
+
TZNAME:Europe/Berlin(STD)
|
|
151
|
+
DTSTART:19471005T030000
|
|
152
|
+
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=1SU;UNTIL=19491002T030000
|
|
153
|
+
END:STANDARD
|
|
154
|
+
BEGIN:DAYLIGHT
|
|
155
|
+
TZOFFSETTO:+020000
|
|
156
|
+
TZOFFSETFROM:+010000
|
|
157
|
+
TZNAME:Europe/Berlin(DST)
|
|
158
|
+
DTSTART:19800406T020000
|
|
159
|
+
RDATE:19800406T020000
|
|
160
|
+
END:DAYLIGHT
|
|
161
|
+
BEGIN:STANDARD
|
|
162
|
+
TZOFFSETTO:+010000
|
|
163
|
+
TZOFFSETFROM:+020000
|
|
164
|
+
TZNAME:Europe/Berlin(STD)
|
|
165
|
+
DTSTART:19800928T030000
|
|
166
|
+
RRULE:FREQ=YEARLY;BYMONTH=9;BYDAY=-1SU;UNTIL=19950924T030000
|
|
167
|
+
END:STANDARD
|
|
168
|
+
BEGIN:DAYLIGHT
|
|
169
|
+
TZOFFSETTO:+020000
|
|
170
|
+
TZOFFSETFROM:+010000
|
|
171
|
+
TZNAME:Europe/Berlin(DST)
|
|
172
|
+
DTSTART:19810329T020000
|
|
173
|
+
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU;UNTIL=19960331T020000
|
|
174
|
+
END:DAYLIGHT
|
|
175
|
+
BEGIN:STANDARD
|
|
176
|
+
TZOFFSETTO:+010000
|
|
177
|
+
TZOFFSETFROM:+020000
|
|
178
|
+
TZNAME:Europe/Berlin(STD)
|
|
179
|
+
DTSTART:19961027T030000
|
|
180
|
+
RDATE:19961027T030000
|
|
181
|
+
END:STANDARD
|
|
182
|
+
BEGIN:DAYLIGHT
|
|
183
|
+
TZOFFSETTO:+020000
|
|
184
|
+
TZOFFSETFROM:+010000
|
|
185
|
+
TZNAME:(DST)
|
|
186
|
+
DTSTART:19970330T020000
|
|
187
|
+
RRULE:FREQ=YEARLY;BYMONTH=3;BYDAY=-1SU
|
|
188
|
+
END:DAYLIGHT
|
|
189
|
+
BEGIN:STANDARD
|
|
190
|
+
TZOFFSETTO:+010000
|
|
191
|
+
TZOFFSETFROM:+020000
|
|
192
|
+
TZNAME:(STD)
|
|
193
|
+
DTSTART:19971026T030000
|
|
194
|
+
RRULE:FREQ=YEARLY;BYMONTH=10;BYDAY=-1SU
|
|
195
|
+
END:STANDARD
|
|
196
|
+
END:VTIMEZONE
|
|
197
|
+
BEGIN:VEVENT
|
|
198
|
+
CREATED:20240823T082735Z
|
|
199
|
+
LAST-MODIFIED:20240823T082802Z
|
|
200
|
+
DTSTAMP:20240823T082802Z
|
|
201
|
+
UID:22d43072-b75a-43da-bed0-a5da8a7a6853
|
|
202
|
+
SUMMARY:Weekly Tuesday Morning Meeting
|
|
203
|
+
RRULE:FREQ=WEEKLY
|
|
204
|
+
DTSTART;TZID=Europe/Berlin:20240820T090000
|
|
205
|
+
DTEND;TZID=Europe/Berlin:20240820T100000
|
|
206
|
+
TRANSP:OPAQUE
|
|
207
|
+
X-MOZ-GENERATION:2
|
|
208
|
+
SEQUENCE:1
|
|
209
|
+
END:VEVENT
|
|
210
|
+
BEGIN:VEVENT
|
|
211
|
+
CREATED:20240823T082829Z
|
|
212
|
+
LAST-MODIFIED:20240823T082915Z
|
|
213
|
+
DTSTAMP:20240823T082915Z
|
|
214
|
+
UID:6b85b60c-eb1a-4338-9ece-33541b95bf17
|
|
215
|
+
SUMMARY:Work
|
|
216
|
+
RRULE:FREQ=DAILY;BYDAY=MO,TU,WE,TH,FR
|
|
217
|
+
DTSTART;TZID=Europe/Berlin:20240819T090000
|
|
218
|
+
DTEND;TZID=Europe/Berlin:20240819T170000
|
|
219
|
+
TRANSP:OPAQUE
|
|
220
|
+
X-MOZ-GENERATION:2
|
|
221
|
+
SEQUENCE:1
|
|
222
|
+
END:VEVENT
|
|
223
|
+
END:VCALENDAR
|
|
File without changes
|
|
File without changes
|
|
@@ -0,0 +1,12 @@
|
|
|
1
|
+
BEGIN:VEVENT
|
|
2
|
+
SUMMARY:Work
|
|
3
|
+
DTSTART;TZID=Europe/Berlin:20240819T090000
|
|
4
|
+
DTEND;TZID=Europe/Berlin:20240819T170000
|
|
5
|
+
DTSTAMP:20240823T082915Z
|
|
6
|
+
UID:6b85b60c-eb1a-4338-9ece-33541b95bf17
|
|
7
|
+
SEQUENCE:1
|
|
8
|
+
CREATED:20240823T082829Z
|
|
9
|
+
LAST-MODIFIED:20240823T082915Z
|
|
10
|
+
TRANSP:OPAQUE
|
|
11
|
+
X-MOZ-GENERATION:2
|
|
12
|
+
END:VEVENT
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
import pytest
|
|
4
4
|
|
|
5
|
-
from ics_query.parse import InvalidTimeFormat, to_time
|
|
5
|
+
from ics_query.parse import InvalidTimeFormat, to_time, to_time_and_delta
|
|
6
6
|
|
|
7
7
|
|
|
8
8
|
@pytest.mark.parametrize(
|
|
@@ -43,9 +43,10 @@ from ics_query.parse import InvalidTimeFormat, to_time
|
|
|
43
43
|
("20141010183012", (2014, 10, 10, 18, 30, 12)),
|
|
44
44
|
],
|
|
45
45
|
)
|
|
46
|
-
|
|
46
|
+
@pytest.mark.parametrize("parser", [to_time_and_delta, to_time])
|
|
47
|
+
def test_parse_to_date_argument(string_argument, expected_result, parser):
|
|
47
48
|
"""Check that we can properly parse what is accepted."""
|
|
48
|
-
result =
|
|
49
|
+
result = parser(string_argument)
|
|
49
50
|
assert result == expected_result
|
|
50
51
|
|
|
51
52
|
|
|
@@ -53,11 +54,13 @@ def test_parse_to_date_argument(string_argument, expected_result):
|
|
|
53
54
|
"dt",
|
|
54
55
|
[
|
|
55
56
|
"",
|
|
57
|
+
" ",
|
|
56
58
|
"132",
|
|
57
59
|
"12345",
|
|
58
60
|
],
|
|
59
61
|
)
|
|
60
|
-
|
|
62
|
+
@pytest.mark.parametrize("parser", [to_time_and_delta, to_time])
|
|
63
|
+
def test_invalid_time_format(dt: str, parser):
|
|
61
64
|
"""Check invalid time formats."""
|
|
62
65
|
with pytest.raises(InvalidTimeFormat):
|
|
63
|
-
|
|
66
|
+
parser(dt)
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
"""This tests parsing input times and dates."""
|
|
2
|
+
|
|
3
|
+
from datetime import timedelta
|
|
4
|
+
|
|
5
|
+
import pytest
|
|
6
|
+
|
|
7
|
+
from ics_query.parse import to_time_and_delta
|
|
8
|
+
|
|
9
|
+
|
|
10
|
+
@pytest.mark.parametrize(
|
|
11
|
+
("string_argument", "expected_result"),
|
|
12
|
+
[
|
|
13
|
+
("10d", timedelta(days=10)),
|
|
14
|
+
("10d10h", timedelta(days=10, hours=10)),
|
|
15
|
+
("1d2h12m33s", timedelta(days=1, hours=2, minutes=12, seconds=33)),
|
|
16
|
+
("3600s", timedelta(seconds=3600)),
|
|
17
|
+
("10m", timedelta(minutes=10)),
|
|
18
|
+
("23h", timedelta(hours=23)),
|
|
19
|
+
],
|
|
20
|
+
)
|
|
21
|
+
@pytest.mark.parametrize("plus", ["", "+"])
|
|
22
|
+
def test_parse_to_date_argument(string_argument, expected_result, plus):
|
|
23
|
+
"""Check that we can properly parse what is accepted."""
|
|
24
|
+
result = to_time_and_delta(plus + string_argument)
|
|
25
|
+
assert result == expected_result
|
|
@@ -15,7 +15,7 @@ maintainers = [
|
|
|
15
15
|
]
|
|
16
16
|
description = "Find out what happens in ICS calendar files - query and filter RFC 5545 compatible .ics files for events, journals, TODOs and more."
|
|
17
17
|
readme = "README.md"
|
|
18
|
-
requires-python = ">=3.
|
|
18
|
+
requires-python = ">=3.9"
|
|
19
19
|
# see https://pypi.python.org/pypi?%3Aaction=list_classifiers
|
|
20
20
|
classifiers = [
|
|
21
21
|
"Development Status :: 3 - Alpha",
|
|
@@ -31,7 +31,7 @@ classifiers = [
|
|
|
31
31
|
|
|
32
32
|
dependencies = [
|
|
33
33
|
"icalendar",
|
|
34
|
-
"recurring-ical-events",
|
|
34
|
+
"recurring-ical-events>=3.2.0,<4",
|
|
35
35
|
"click",
|
|
36
36
|
"icalendar",
|
|
37
37
|
]
|
|
@@ -4,10 +4,12 @@
|
|
|
4
4
|
# and then run "tox" from this directory.
|
|
5
5
|
|
|
6
6
|
[tox]
|
|
7
|
+
skipsdist = True
|
|
7
8
|
envlist = py39, py310, py311, py312, ruff
|
|
8
9
|
|
|
9
10
|
[testenv]
|
|
10
|
-
deps =
|
|
11
|
+
deps =
|
|
12
|
+
-e {tox_root}[test]
|
|
11
13
|
setenv = TMPDIR={envtmpdir}
|
|
12
14
|
commands =
|
|
13
15
|
pytest --basetemp="{envtmpdir}" {posargs}
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/tests/runs/at 2019-03-04 one-event-twice.ics -.run
RENAMED
|
File without changes
|
{ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/tests/runs/at 2019-03-04 one-event.ics -.run
RENAMED
|
File without changes
|
|
File without changes
|
{ics_query-0.1.1a0 → ics_query-0.2.0a0}/ics_query/tests/runs/calendars/multiple-calendars.ics
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|