1# Copyright 2021 gRPC authors.
2#
3# Licensed under the Apache License, Version 2.0 (the "License");
4# you may not use this file except in compliance with the License.
5# You may obtain a copy of the License at
6#
7#     http://www.apache.org/licenses/LICENSE-2.0
8#
9# Unless required by applicable law or agreed to in writing, software
10# distributed under the License is distributed on an "AS IS" BASIS,
11# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12# See the License for the specific language governing permissions and
13# limitations under the License.
14"""This contains common helpers for working with dates and time."""
15import datetime
16import re
17from typing import Pattern
18
19RE_ZERO_OFFSET: Pattern[str] = re.compile(r'[+\-]00:?00$')
20
21
22def utc_now() -> datetime.datetime:
23    """Construct a datetime from current time in UTC timezone."""
24    return datetime.datetime.now(datetime.timezone.utc)
25
26
27def shorten_utc_zone(utc_datetime_str: str) -> str:
28    """Replace ±00:00 timezone designator with Z (zero offset AKA Zulu time)."""
29    return RE_ZERO_OFFSET.sub('Z', utc_datetime_str)
30
31
32def iso8601_utc_time(time: datetime.datetime = None) -> str:
33    """Converts datetime UTC and formats as ISO-8601 Zulu time."""
34    utc_time = time.astimezone(tz=datetime.timezone.utc)
35    return shorten_utc_zone(utc_time.isoformat())
36
37
38def datetime_suffix(*, seconds: bool = False) -> str:
39    """Return current UTC date, and time in a format useful for resource naming.
40
41    Examples:
42        - 20210626-1859   (seconds=False)
43        - 20210626-185942 (seconds=True)
44    Use in resources names incompatible with ISO 8601, e.g. some GCP resources
45    that only allow lowercase alphanumeric chars and dashes.
46
47    Hours and minutes are joined together for better readability, so time is
48    visually distinct from dash-separated date.
49    """
50    return utc_now().strftime('%Y%m%d-%H%M' + ('%S' if seconds else ''))
51