Mercurial > libervia-backend
annotate libervia/backend/tools/xmpp_datetime.py @ 4306:94e0968987cd
plugin XEP-0033: code modernisation, improve delivery, data validation:
- Code has been rewritten using Pydantic models and `async` coroutines for data validation
and cleaner element parsing/generation.
- Delivery has been completely rewritten. It now works even if server doesn't support
multicast, and send to local multicast service first. Delivering to local multicast
service first is due to bad support of XEP-0033 in server (notably Prosody which has an
incomplete implementation), and the current impossibility to detect if a sub-domain
service handles fully multicast or only for local domains. This is a workaround to have
a good balance between backward compatilibity and use of bandwith, and to make it work
with the incoming email gateway implementation (the gateway will only deliver to
entities of its own domain).
- disco feature checking now uses `async` corountines. `host` implementation still use
Deferred return values for compatibility with legacy code.
rel 450
author | Goffi <goffi@goffi.org> |
---|---|
date | Thu, 26 Sep 2024 16:12:01 +0200 |
parents | 0d7bb4df2343 |
children |
rev | line source |
---|---|
3877
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
1 #!/usr/bin/env python3 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
2 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
3 # Libervia: XMPP Date and Time profiles as per XEP-0082 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
4 # Copyright (C) 2022-2022 Tim Henkes (me@syndace.dev) |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
5 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
6 # This program is free software: you can redistribute it and/or modify |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
7 # it under the terms of the GNU Affero General Public License as published by |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
8 # the Free Software Foundation, either version 3 of the License, or |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
9 # (at your option) any later version. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
10 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
11 # This program is distributed in the hope that it will be useful, |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
12 # but WITHOUT ANY WARRANTY; without even the implied warranty of |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
13 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
14 # GNU Affero General Public License for more details. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
15 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
16 # You should have received a copy of the GNU Affero General Public License |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
17 # along with this program. If not, see <http://www.gnu.org/licenses/>. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
18 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
19 from datetime import date, datetime, time, timezone |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
20 import re |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
21 from typing import Optional, Tuple |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
22 |
4071
4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
Goffi <goffi@goffi.org>
parents:
3933
diff
changeset
|
23 from libervia.backend.core import exceptions |
3911
8289ac1b34f4
plugin XEP-0384: Fully reworked to adjust to the reworked python-omemo:
Syndace <me@syndace.dev>
parents:
3879
diff
changeset
|
24 |
3877
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
25 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
26 __all__ = [ # pylint: disable=unused-variable |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
27 "format_date", |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
28 "parse_date", |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
29 "format_datetime", |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
30 "parse_datetime", |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
31 "format_time", |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
32 "parse_time", |
3877
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
33 ] |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
34 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
35 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
36 def __parse_fraction_of_a_second(value: str) -> Tuple[str, Optional[int]]: |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
37 """ |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
38 datetime's strptime only supports up to six digits of the fraction of a seconds, while |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
39 the XEP-0082 specification allows for any number of digits. This function parses and |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
40 removes the optional fraction of a second from the input string. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
41 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
42 @param value: The input string, containing a section of the format [.sss]. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
43 @return: The input string with the fraction of a second removed, and the fraction of a |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
44 second parsed with microsecond resolution. Returns the unaltered input string and |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
45 ``None`` if no fraction of a second was found in the input string. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
46 """ |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
47 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
48 # The following regex matches the optional fraction of a seconds for manual |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
49 # processing. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
50 match = re.search(r"\.(\d*)", value) |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
51 microsecond: Optional[int] = None |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
52 if match is not None: |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
53 # Remove the fraction of a second from the input string |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
54 value = value[: match.start()] + value[match.end() :] |
3877
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
55 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
56 # datetime supports microsecond resolution for the fraction of a second, thus |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
57 # limit/pad the parsed fraction of a second to six digits |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
58 microsecond = int(match.group(1)[:6].ljust(6, "0")) |
3877
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
59 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
60 return value, microsecond |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
61 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
62 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
63 def format_date(value: Optional[date] = None) -> str: |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
64 """ |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
65 @param value: The date for format. Defaults to the current date in the UTC timezone. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
66 @return: The date formatted according to the Date profile specified in XEP-0082. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
67 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
68 @warning: Formatting of the current date in the local timezone may leak geographical |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
69 information of the sender. Thus, it is advised to only format the current date in |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
70 UTC. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
71 """ |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
72 # CCYY-MM-DD |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
73 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
74 # The Date profile of XEP-0082 is equal to the ISO 8601 format. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
75 return (datetime.now(timezone.utc).date() if value is None else value).isoformat() |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
76 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
77 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
78 def parse_date(value: str) -> date: |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
79 """ |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
80 @param value: A string containing date information formatted according to the Date |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
81 profile specified in XEP-0082. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
82 @return: The date parsed from the input string. |
3933
cecf45416403
plugin XEP-0373 and XEP-0374: Implementation of OX and OXIM:
Syndace <me@syndace.dev>
parents:
3911
diff
changeset
|
83 @raise exceptions.ParsingError: if the input string is not correctly formatted. |
3877
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
84 """ |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
85 # CCYY-MM-DD |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
86 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
87 # The Date profile of XEP-0082 is equal to the ISO 8601 format. |
3933
cecf45416403
plugin XEP-0373 and XEP-0374: Implementation of OX and OXIM:
Syndace <me@syndace.dev>
parents:
3911
diff
changeset
|
88 try: |
cecf45416403
plugin XEP-0373 and XEP-0374: Implementation of OX and OXIM:
Syndace <me@syndace.dev>
parents:
3911
diff
changeset
|
89 return date.fromisoformat(value) |
cecf45416403
plugin XEP-0373 and XEP-0374: Implementation of OX and OXIM:
Syndace <me@syndace.dev>
parents:
3911
diff
changeset
|
90 except ValueError as e: |
cecf45416403
plugin XEP-0373 and XEP-0374: Implementation of OX and OXIM:
Syndace <me@syndace.dev>
parents:
3911
diff
changeset
|
91 raise exceptions.ParsingError() from e |
3877
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
92 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
93 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
94 def format_datetime( |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
95 value: Optional[datetime] = None, include_microsecond: bool = False |
3877
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
96 ) -> str: |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
97 """ |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
98 @param value: The datetime to format. Defaults to the current datetime. |
3878
32087d7c25d4
tools (datetime, utils): fix incorrect use of naive object:
Goffi <goffi@goffi.org>
parents:
3877
diff
changeset
|
99 must be an aware datetime object (timezone must be specified) |
3877
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
100 @param include_microsecond: Include the microsecond of the datetime in the output. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
101 @return: The datetime formatted according to the DateTime profile specified in |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
102 XEP-0082. The datetime is always converted to UTC before formatting to avoid |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
103 leaking geographical information of the sender. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
104 """ |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
105 # CCYY-MM-DDThh:mm:ss[.sss]TZD |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
106 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
107 # We format the time in UTC, since the %z formatter of strftime doesn't include colons |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
108 # to separate hours and minutes which is required by XEP-0082. UTC allows us to put a |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
109 # simple letter 'Z' as the time zone definition. |
3878
32087d7c25d4
tools (datetime, utils): fix incorrect use of naive object:
Goffi <goffi@goffi.org>
parents:
3877
diff
changeset
|
110 if value is not None: |
32087d7c25d4
tools (datetime, utils): fix incorrect use of naive object:
Goffi <goffi@goffi.org>
parents:
3877
diff
changeset
|
111 if value.tzinfo is None: |
32087d7c25d4
tools (datetime, utils): fix incorrect use of naive object:
Goffi <goffi@goffi.org>
parents:
3877
diff
changeset
|
112 raise exceptions.InternalError( |
32087d7c25d4
tools (datetime, utils): fix incorrect use of naive object:
Goffi <goffi@goffi.org>
parents:
3877
diff
changeset
|
113 "an aware datetime object must be used, but a naive one has been provided" |
32087d7c25d4
tools (datetime, utils): fix incorrect use of naive object:
Goffi <goffi@goffi.org>
parents:
3877
diff
changeset
|
114 ) |
32087d7c25d4
tools (datetime, utils): fix incorrect use of naive object:
Goffi <goffi@goffi.org>
parents:
3877
diff
changeset
|
115 value = value.astimezone(timezone.utc) # pylint: disable=no-member |
32087d7c25d4
tools (datetime, utils): fix incorrect use of naive object:
Goffi <goffi@goffi.org>
parents:
3877
diff
changeset
|
116 else: |
32087d7c25d4
tools (datetime, utils): fix incorrect use of naive object:
Goffi <goffi@goffi.org>
parents:
3877
diff
changeset
|
117 value = datetime.now(timezone.utc) |
3877
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
118 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
119 if include_microsecond: |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
120 return value.strftime("%Y-%m-%dT%H:%M:%S.%fZ") |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
121 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
122 return value.strftime("%Y-%m-%dT%H:%M:%SZ") |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
123 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
124 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
125 def parse_datetime(value: str) -> datetime: |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
126 """ |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
127 @param value: A string containing datetime information formatted according to the |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
128 DateTime profile specified in XEP-0082. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
129 @return: The datetime parsed from the input string. |
3933
cecf45416403
plugin XEP-0373 and XEP-0374: Implementation of OX and OXIM:
Syndace <me@syndace.dev>
parents:
3911
diff
changeset
|
130 @raise exceptions.ParsingError: if the input string is not correctly formatted. |
3877
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
131 """ |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
132 # CCYY-MM-DDThh:mm:ss[.sss]TZD |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
133 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
134 value, microsecond = __parse_fraction_of_a_second(value) |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
135 |
3933
cecf45416403
plugin XEP-0373 and XEP-0374: Implementation of OX and OXIM:
Syndace <me@syndace.dev>
parents:
3911
diff
changeset
|
136 try: |
cecf45416403
plugin XEP-0373 and XEP-0374: Implementation of OX and OXIM:
Syndace <me@syndace.dev>
parents:
3911
diff
changeset
|
137 result = datetime.strptime(value, "%Y-%m-%dT%H:%M:%S%z") |
cecf45416403
plugin XEP-0373 and XEP-0374: Implementation of OX and OXIM:
Syndace <me@syndace.dev>
parents:
3911
diff
changeset
|
138 except ValueError as e: |
cecf45416403
plugin XEP-0373 and XEP-0374: Implementation of OX and OXIM:
Syndace <me@syndace.dev>
parents:
3911
diff
changeset
|
139 raise exceptions.ParsingError() from e |
3877
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
140 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
141 if microsecond is not None: |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
142 result = result.replace(microsecond=microsecond) |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
143 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
144 return result |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
145 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
146 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
147 def format_time(value: Optional[time] = None, include_microsecond: bool = False) -> str: |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
148 """ |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
149 @param value: The time to format. Defaults to the current time in the UTC timezone. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
150 @param include_microsecond: Include the microsecond of the time in the output. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
151 @return: The time formatted according to the Time profile specified in XEP-0082. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
152 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
153 @warning: Since accurate timezone conversion requires the date to be known, this |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
154 function cannot convert input times to UTC before formatting. This means that |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
155 geographical information of the sender may be leaked if a time in local timezone |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
156 is formatted. Thus, when passing a time to format, it is advised to pass the time |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
157 in UTC if possible. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
158 """ |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
159 # hh:mm:ss[.sss][TZD] |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
160 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
161 if value is None: |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
162 # There is no time.now() method as one might expect, but the current time can be |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
163 # extracted from a datetime object including time zone information. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
164 value = datetime.now(timezone.utc).timetz() |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
165 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
166 # The format created by time.isoformat complies with the XEP-0082 Time profile. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
167 return value.isoformat("auto" if include_microsecond else "seconds") |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
168 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
169 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
170 def parse_time(value: str) -> time: |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
171 """ |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
172 @param value: A string containing time information formatted according to the Time |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
173 profile specified in XEP-0082. |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
174 @return: The time parsed from the input string. |
3933
cecf45416403
plugin XEP-0373 and XEP-0374: Implementation of OX and OXIM:
Syndace <me@syndace.dev>
parents:
3911
diff
changeset
|
175 @raise exceptions.ParsingError: if the input string is not correctly formatted. |
3877
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
176 """ |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
177 # hh:mm:ss[.sss][TZD] |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
178 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
179 value, microsecond = __parse_fraction_of_a_second(value) |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
180 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
181 # The format parsed by time.fromisoformat mostly complies with the XEP-0082 Time |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
182 # profile, except that it doesn't handle the letter Z as time zone information for |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
183 # UTC. This can be fixed with a simple string replacement of 'Z' with "+00:00", which |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
184 # is another way to represent UTC. |
3933
cecf45416403
plugin XEP-0373 and XEP-0374: Implementation of OX and OXIM:
Syndace <me@syndace.dev>
parents:
3911
diff
changeset
|
185 try: |
4270
0d7bb4df2343
Reformatted code base using black.
Goffi <goffi@goffi.org>
parents:
4071
diff
changeset
|
186 result = time.fromisoformat(value.replace("Z", "+00:00")) |
3933
cecf45416403
plugin XEP-0373 and XEP-0374: Implementation of OX and OXIM:
Syndace <me@syndace.dev>
parents:
3911
diff
changeset
|
187 except ValueError as e: |
cecf45416403
plugin XEP-0373 and XEP-0374: Implementation of OX and OXIM:
Syndace <me@syndace.dev>
parents:
3911
diff
changeset
|
188 raise exceptions.ParsingError() from e |
3877
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
189 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
190 if microsecond is not None: |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
191 result = result.replace(microsecond=microsecond) |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
192 |
00212260f659
plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff
changeset
|
193 return result |