clock: Detect system TZ (if possible) for cases where no TZ is specified
When the pytz dep was reintroduced, this made all TZ usage reliant upon a tzinfo object generated by pytz. This had the effect of making the ``%Z`` strftime placeholder evaluate as blank when a timezone is not explicitly defined (i.e. when the format is just a format string and not a tuple containing the format string and timezone). This commit resolves this regression by using pytz to build a tzinfo object from either /etc/localtime or /etc/timezone during the ``init()`` function, establishing the system TZ to be used for those cases where no TZ was specified.
This commit is contained in:
parent
03df1a644a
commit
3590dd20e5
@ -1,7 +1,14 @@
|
|||||||
|
import errno
|
||||||
import os
|
import os
|
||||||
import locale
|
import locale
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
|
|
||||||
|
try:
|
||||||
|
import pytz
|
||||||
|
HAS_PYTZ = True
|
||||||
|
except ImportError:
|
||||||
|
HAS_PYTZ = False
|
||||||
|
|
||||||
from i3pystatus import IntervalModule
|
from i3pystatus import IntervalModule
|
||||||
|
|
||||||
|
|
||||||
@ -85,21 +92,64 @@ class Clock(IntervalModule):
|
|||||||
|
|
||||||
elif isinstance(self.format, str) or isinstance(self.format, tuple):
|
elif isinstance(self.format, str) or isinstance(self.format, tuple):
|
||||||
self.format = [self.format]
|
self.format = [self.format]
|
||||||
|
|
||||||
|
self.system_tz = self._get_system_tz()
|
||||||
self.format = [self._expand_format(fmt) for fmt in self.format]
|
self.format = [self._expand_format(fmt) for fmt in self.format]
|
||||||
self.current_format_id = 0
|
self.current_format_id = 0
|
||||||
|
|
||||||
@staticmethod
|
def _expand_format(self, fmt):
|
||||||
def _expand_format(fmt):
|
|
||||||
if isinstance(fmt, tuple):
|
if isinstance(fmt, tuple):
|
||||||
if len(fmt) == 1:
|
if len(fmt) == 1:
|
||||||
return (fmt[0], None)
|
return (fmt[0], None)
|
||||||
else:
|
else:
|
||||||
|
if not HAS_PYTZ:
|
||||||
|
raise RuntimeError("Need `pytz` for timezone data")
|
||||||
|
return (fmt[0], pytz.timezone(fmt[1]))
|
||||||
|
return (fmt, self.system_tz)
|
||||||
|
|
||||||
|
def _get_system_tz(self):
|
||||||
|
'''
|
||||||
|
Get the system timezone for use when no timezone is explicitly provided
|
||||||
|
|
||||||
|
Requires pytz, if not available then no timezone will be set when not
|
||||||
|
explicitly provided.
|
||||||
|
'''
|
||||||
|
if not HAS_PYTZ:
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _etc_localtime():
|
||||||
try:
|
try:
|
||||||
from pytz import timezone
|
with open('/etc/localtime', 'rb') as fp:
|
||||||
except ImportError as e:
|
return pytz.tzfile.build_tzinfo('system', fp)
|
||||||
raise RuntimeError("Need `pytz` for timezone data") from e
|
except OSError as exc:
|
||||||
return (fmt[0], timezone(fmt[1]))
|
if exc.errno != errno.ENOENT:
|
||||||
return (fmt, None)
|
self.logger.error(
|
||||||
|
'Unable to read from /etc/localtime: %s', exc.strerror
|
||||||
|
)
|
||||||
|
except pytz.UnknownTimeZoneError:
|
||||||
|
self.logger.error(
|
||||||
|
'/etc/localtime contains unrecognized tzinfo'
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
def _etc_timezone():
|
||||||
|
try:
|
||||||
|
with open('/etc/timezone', 'r') as fp:
|
||||||
|
tzname = fp.read().strip()
|
||||||
|
return pytz.timezone(tzname)
|
||||||
|
except OSError as exc:
|
||||||
|
if exc.errno != errno.ENOENT:
|
||||||
|
self.logger.error(
|
||||||
|
'Unable to read from /etc/localtime: %s', exc.strerror
|
||||||
|
)
|
||||||
|
except pytz.UnknownTimeZoneError:
|
||||||
|
self.logger.error(
|
||||||
|
'/etc/timezone contains unrecognized timezone \'%s\'',
|
||||||
|
tzname
|
||||||
|
)
|
||||||
|
return None
|
||||||
|
|
||||||
|
return _etc_localtime() or _etc_timezone()
|
||||||
|
|
||||||
def run(self):
|
def run(self):
|
||||||
time = datetime.now(self.format[self.current_format_id][1])
|
time = datetime.now(self.format[self.current_format_id][1])
|
||||||
|
Loading…
Reference in New Issue
Block a user