timeTools.py 2.2 KB

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