aboutsummaryrefslogtreecommitdiff
path: root/diplomacy/utils/time.py
diff options
context:
space:
mode:
authorPhilip Paquette <pcpaquette@gmail.com>2018-09-26 07:48:55 -0400
committerPhilip Paquette <pcpaquette@gmail.com>2019-04-18 11:14:24 -0400
commit6187faf20384b0c5a4966343b2d4ca47f8b11e45 (patch)
tree151ccd21aea20180432c13fe4b58240d3d9e98b6 /diplomacy/utils/time.py
parent96b7e2c03ed98705754f13ae8efa808b948ee3a8 (diff)
Release v1.0.0 - Diplomacy Game Engine - AGPL v3+ License
Diffstat (limited to 'diplomacy/utils/time.py')
-rw-r--r--diplomacy/utils/time.py85
1 files changed, 85 insertions, 0 deletions
diff --git a/diplomacy/utils/time.py b/diplomacy/utils/time.py
new file mode 100644
index 0000000..6f250dd
--- /dev/null
+++ b/diplomacy/utils/time.py
@@ -0,0 +1,85 @@
+# ==============================================================================
+# Copyright (C) 2019 - Philip Paquette
+#
+# This program is free software: you can redistribute it and/or modify it under
+# the terms of the GNU Affero General Public License as published by the Free
+# Software Foundation, either version 3 of the License, or (at your option) any
+# later version.
+#
+# This program is distributed in the hope that it will be useful, but WITHOUT
+# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
+# FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for more
+# details.
+#
+# You should have received a copy of the GNU Affero General Public License along
+# with this program. If not, see <https://www.gnu.org/licenses/>.
+# ==============================================================================
+""" Time functions
+ - Contains generic time functions (e.g. to calculate deadlines)
+"""
+import calendar
+import datetime
+import math
+import pytz
+
+def str_to_seconds(offset_str):
+ """ Converts a time in format 00W00D00H00M00S in number of seconds
+ :param offset_str: The string to convert (e.g. '20D')
+ :return: Its equivalent in seconds = 1728000
+ """
+ mult = {'W': 7 * 24 * 60 * 60, 'D': 24 * 60 * 60, 'H': 60 * 60, 'M': 60, 'S': 1, ' ': 1}
+ buffer = current_sum = 0
+ offset_str = str(offset_str)
+
+ # Adding digits to buffer, when a character is found,
+ # multiply it with buffer and increase the current_sum
+ for char in offset_str:
+ if char.isdigit():
+ buffer = buffer * 10 + int(char)
+ elif char.upper() in mult:
+ current_sum += buffer * mult[char.upper()]
+ buffer = 0
+ else:
+ buffer = 0
+ current_sum += buffer
+
+ return current_sum
+
+def trunc_time(timestamp, trunc_interval, time_zone='GMT'):
+ """ Truncates time at a specific interval (e.g. 20M) (i.e. Rounds to the next :20, :40, :60)
+ :param timestamp: The unix epoch to truncate (e.g. 1498746120)
+ :param trunc_interval: The truncation interval (e.g. 60*60 or '1H')
+ :param time_zone: The time to use for conversion (defaults to GMT otherwise)
+ :return: A timestamp truncated to the nearest (future) interval
+ """
+ midnight_ts = calendar.timegm(datetime.datetime.combine(datetime.date.today(), datetime.time.min).utctimetuple())
+ midnight_offset = (timestamp - midnight_ts) % (24*3600)
+
+ dtime = datetime.datetime.fromtimestamp(timestamp, pytz.timezone(time_zone))
+ tz_offset = dtime.utcoffset().total_seconds()
+ interval = str_to_seconds(trunc_interval)
+ trunc_offset = math.ceil((midnight_offset + tz_offset) / interval) * interval
+
+ trunc_ts = timestamp - midnight_offset + trunc_offset - tz_offset
+ return int(trunc_ts)
+
+def next_time_at(timestamp, time_at, time_zone='GMT'):
+ """ Returns the next timestamp at a specific 'hh:mm'
+ :param timestamp: The unix timestamp to convert
+ :param time_at: The next 'hh:mm' to have the time rounded to, or 0 to skip
+ :param time_zone: The time to use for conversion (defaults to GMT otherwise)
+ :return: A timestamp truncated to the nearest (future) hh:mm
+ """
+ if not time_at:
+ return timestamp
+
+ midnight_ts = calendar.timegm(datetime.datetime.combine(datetime.date.today(), datetime.time.min).utctimetuple())
+ midnight_offset = (timestamp - midnight_ts) % (24*3600)
+
+ dtime = datetime.datetime.fromtimestamp(timestamp, pytz.timezone(time_zone))
+ tz_offset = dtime.utcoffset().total_seconds()
+ trunc_interval = '%dH%dM' % (int(time_at.split(':')[0]), int(time_at.split(':')[1])) if ':' in time_at else time_at
+ interval = str_to_seconds(trunc_interval)
+ at_offset = (-midnight_offset + interval - tz_offset) % (24 * 3600)
+ at_ts = timestamp + at_offset
+ return int(at_ts)