annotate sat/tools/xmpp_datetime.py @ 3913:944f51f9c2b4

core (xmpp): make `send` a blocking method, fix `sendMessageData` calls: original `send` method is blocking, and it is used as such by Wokkel and thus can't be changed to an async method easily. However, an Async method is necessary to have an async trigger at the very end of the send workflow for end-to-end encryption. To workaround that, `send` is an async method which call `a_send`, an async method which actually does the sending. This way legacy method can still call `send` while `a_send` can be await otherwise. Fix calls to `sendMessageData`: the method now being an `async` one, `ensureDeferred` had to be used in some calls.
author Goffi <goffi@goffi.org>
date Sat, 24 Sep 2022 16:31:39 +0200
parents 8289ac1b34f4
children cecf45416403
Ignore whitespace changes - Everywhere: Within whitespace: At end of lines:
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
3911
8289ac1b34f4 plugin XEP-0384: Fully reworked to adjust to the reworked python-omemo:
Syndace <me@syndace.dev>
parents: 3879
diff changeset
23 from sat.core import exceptions
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",
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
32 "parse_time"
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
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
54 value = value[:match.start()] + value[match.end():]
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
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
58 microsecond = int(match.group(1)[:6].ljust(6, '0'))
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.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
83 @raise ValueError: if the input string is not correctly formatted.
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.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
88 return date.fromisoformat(value)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
89
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
90
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
91 def format_datetime(
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
92 value: Optional[datetime] = None,
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
93 include_microsecond: bool = False
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
94 ) -> str:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
95 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
96 @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
97 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
98 @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
99 @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
100 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
101 leaking geographical information of the sender.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
102 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
103 # CCYY-MM-DDThh:mm:ss[.sss]TZD
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 # 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
106 # 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
107 # 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
108 if value is not None:
32087d7c25d4 tools (datetime, utils): fix incorrect use of naive object:
Goffi <goffi@goffi.org>
parents: 3877
diff changeset
109 if value.tzinfo is None:
32087d7c25d4 tools (datetime, utils): fix incorrect use of naive object:
Goffi <goffi@goffi.org>
parents: 3877
diff changeset
110 raise exceptions.InternalError(
32087d7c25d4 tools (datetime, utils): fix incorrect use of naive object:
Goffi <goffi@goffi.org>
parents: 3877
diff changeset
111 "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
112 )
32087d7c25d4 tools (datetime, utils): fix incorrect use of naive object:
Goffi <goffi@goffi.org>
parents: 3877
diff changeset
113 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
114 else:
32087d7c25d4 tools (datetime, utils): fix incorrect use of naive object:
Goffi <goffi@goffi.org>
parents: 3877
diff changeset
115 value = datetime.now(timezone.utc)
3877
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
116
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
117 if include_microsecond:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
118 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
119
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:%SZ")
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
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
123 def parse_datetime(value: str) -> datetime:
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 @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
126 DateTime profile specified in XEP-0082.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
127 @return: The datetime parsed from the input string.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
128 @raise ValueError: if the input string is not correctly formatted.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
129 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
130 # CCYY-MM-DDThh:mm:ss[.sss]TZD
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 value, microsecond = __parse_fraction_of_a_second(value)
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 result = datetime.strptime(value, "%Y-%m-%dT%H:%M:%S%z")
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
135
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
136 if microsecond is not None:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
137 result = result.replace(microsecond=microsecond)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
138
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
139 return result
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
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
142 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
143 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
144 @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
145 @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
146 @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
147
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
148 @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
149 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
150 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
151 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
152 in UTC if possible.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
153 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
154 # hh:mm:ss[.sss][TZD]
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
155
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
156 if value is None:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
157 # 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
158 # 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
159 value = datetime.now(timezone.utc).timetz()
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 # 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
162 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
163
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
164
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
165 def parse_time(value: str) -> time:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
166 """
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
167 @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
168 profile specified in XEP-0082.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
169 @return: The time parsed from the input string.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
170 @raise ValueError: if the input string is not correctly formatted.
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 # hh:mm:ss[.sss][TZD]
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
173
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
174 value, microsecond = __parse_fraction_of_a_second(value)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
175
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
176 # 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
177 # 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
178 # 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
179 # is another way to represent UTC.
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
180 result = time.fromisoformat(value.replace('Z', "+00:00"))
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
181
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
182 if microsecond is not None:
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
183 result = result.replace(microsecond=microsecond)
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
184
00212260f659 plugin XEP-0420: Implementation of Stanza Content Encryption:
Syndace <me@syndace.dev>
parents:
diff changeset
185 return result