forked from yojc/BillyMays_0.16.12
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbilly_sopel_time.py
144 lines (120 loc) · 5.13 KB
/
billy_sopel_time.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
# coding=utf-8
"""Tools for getting and displaying the time."""
from __future__ import unicode_literals, absolute_import, print_function, division
import datetime
try:
import pytz
except:
pytz = False
def validate_timezone(zone):
"""Return an IETF timezone from the given IETF zone or common abbreviation.
If the length of the zone is 4 or less, it will be upper-cased before being
looked up; otherwise it will be title-cased. This is the expected
case-insensitivity behavior in the majority of cases. For example, ``'edt'``
and ``'america/new_york'`` will both return ``'America/New_York'``.
If the zone is not valid, ``ValueError`` will be raised. If ``pytz`` is not
available, and the given zone is anything other than ``'UTC'``,
``ValueError`` will be raised.
"""
if zone is None:
return None
if not pytz:
if zone.upper() != 'UTC':
raise ValueError('Only UTC available, since pytz is not installed.')
else:
return zone
zone = '/'.join(reversed(zone.split(', '))).replace(' ', '_')
if len(zone) <= 4:
zone = zone.upper()
else:
zone = zone.title()
if zone in pytz.all_timezones:
return zone
else:
raise ValueError("Invalid time zone.")
def validate_format(tformat):
"""Returns the format, if valid, else None"""
try:
time = datetime.datetime.utcnow()
time.strftime(tformat)
except:
raise ValueError('Invalid time format')
return tformat
def get_timezone(db=None, config=None, zone=None, nick=None, channel=None):
"""Find, and return, the approriate timezone
Time zone is pulled in the following priority:
1. `zone`, if it is valid
2. The timezone for the channel or nick `zone` in `db` if one is set and
valid.
3. The timezone for the nick `nick` in `db`, if one is set and valid.
4. The timezone for the channel `channel` in `db`, if one is set and valid.
5. The default timezone in `config`, if one is set and valid.
If `db` is not given, or given but not set up, steps 2 and 3 will be
skipped. If `config` is not given, step 4 will be skipped. If no step
yeilds a valid timezone, `None` is returned.
Valid timezones are those present in the IANA Time Zone Database. Prior to
checking timezones, two translations are made to make the zone names more
human-friendly. First, the string is split on `', '`, the pieces reversed,
and then joined with `'/'`. Next, remaining spaces are replaced with `'_'`.
Finally, strings longer than 4 characters are made title-case, and those 4
characters and shorter are made upper-case. This means "new york, america"
becomes "America/New_York", and "utc" becomes "UTC".
This function relies on `pytz` being available. If it is not available,
`None` will always be returned.
"""
def _check(zone):
try:
return validate_timezone(zone)
except ValueError:
return None
if not pytz:
return None
tz = None
if zone:
tz = _check(zone)
if not tz:
tz = _check(
db.get_nick_or_channel_value(zone, 'timezone'))
if not tz and nick:
tz = _check(db.get_nick_value(nick, 'timezone'))
if not tz and channel:
tz = _check(db.get_channel_value(channel, 'timezone'))
if not tz and config and config.core.default_timezone:
tz = _check(config.core.default_timezone)
return tz
def format_time(db=None, config=None, zone=None, nick=None, channel=None,
time=None):
"""Return a formatted string of the given time in the given zone.
`time`, if given, should be a naive `datetime.datetime` object and will be
treated as being in the UTC timezone. If it is not given, the current time
will be used. If `zone` is given and `pytz` is available, `zone` must be
present in the IANA Time Zone Database; `get_timezone` can be helpful for
this. If `zone` is not given or `pytz` is not available, UTC will be
assumed.
The format for the string is chosen in the following order:
1. The format for the nick `nick` in `db`, if one is set and valid.
2. The format for the channel `channel` in `db`, if one is set and valid.
3. The default format in `config`, if one is set and valid.
4. ISO-8601
If `db` is not given or is not set up, steps 1 and 2 are skipped. If config
is not given, step 3 will be skipped."""
tformat = None
if db:
if nick:
tformat = db.get_nick_value(nick, 'time_format')
if not tformat and channel:
tformat = db.get_channel_value(channel, 'time_format')
if not tformat and config and config.core.default_time_format:
tformat = config.core.default_time_format
if not tformat:
tformat = '%Y-%m-%d o godzinie %T%Z'
if not time:
time = datetime.datetime.utcnow()
if not pytz or not zone:
return time.strftime(tformat)
else:
if not time.tzinfo:
utc = pytz.timezone('UTC')
time = utc.localize(time)
zone = pytz.timezone(zone)
return time.astimezone(zone).strftime(tformat)