xref: /aosp_15_r20/external/fonttools/Lib/fontTools/misc/timeTools.py (revision e1fe3e4ad2793916b15cccdc4a7da52a7e1dd0e9)
1"""fontTools.misc.timeTools.py -- tools for working with OpenType timestamps.
2"""
3
4import os
5import time
6from datetime import datetime, timezone
7import calendar
8
9
10epoch_diff = calendar.timegm((1904, 1, 1, 0, 0, 0, 0, 0, 0))
11
12DAYNAMES = ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]
13MONTHNAMES = [
14    None,
15    "Jan",
16    "Feb",
17    "Mar",
18    "Apr",
19    "May",
20    "Jun",
21    "Jul",
22    "Aug",
23    "Sep",
24    "Oct",
25    "Nov",
26    "Dec",
27]
28
29
30def asctime(t=None):
31    """
32    Convert a tuple or struct_time representing a time as returned by gmtime()
33    or localtime() to a 24-character string of the following form:
34
35    >>> asctime(time.gmtime(0))
36    'Thu Jan  1 00:00:00 1970'
37
38    If t is not provided, the current time as returned by localtime() is used.
39    Locale information is not used by asctime().
40
41    This is meant to normalise the output of the built-in time.asctime() across
42    different platforms and Python versions.
43    In Python 3.x, the day of the month is right-justified, whereas on Windows
44    Python 2.7 it is padded with zeros.
45
46    See https://github.com/fonttools/fonttools/issues/455
47    """
48    if t is None:
49        t = time.localtime()
50    s = "%s %s %2s %s" % (
51        DAYNAMES[t.tm_wday],
52        MONTHNAMES[t.tm_mon],
53        t.tm_mday,
54        time.strftime("%H:%M:%S %Y", t),
55    )
56    return s
57
58
59def timestampToString(value):
60    return asctime(time.gmtime(max(0, value + epoch_diff)))
61
62
63def timestampFromString(value):
64    wkday, mnth = value[:7].split()
65    t = datetime.strptime(value[7:], " %d %H:%M:%S %Y")
66    t = t.replace(month=MONTHNAMES.index(mnth), tzinfo=timezone.utc)
67    wkday_idx = DAYNAMES.index(wkday)
68    assert t.weekday() == wkday_idx, '"' + value + '" has inconsistent weekday'
69    return int(t.timestamp()) - epoch_diff
70
71
72def timestampNow():
73    # https://reproducible-builds.org/specs/source-date-epoch/
74    source_date_epoch = os.environ.get("SOURCE_DATE_EPOCH")
75    if source_date_epoch is not None:
76        return int(source_date_epoch) - epoch_diff
77    return int(time.time() - epoch_diff)
78
79
80def timestampSinceEpoch(value):
81    return int(value - epoch_diff)
82
83
84if __name__ == "__main__":
85    import sys
86    import doctest
87
88    sys.exit(doctest.testmod().failed)
89