# -*- coding: utf-8 -*- # This file is part of pygal # # A python svg graph plotting library # Copyright © 2012-2016 Kozea # # This library is free software: you can redistribute it and/or modify it under # the terms of the GNU Lesser General Public License as published by the Free # Software Foundation, either version 3 of the License, or (at your option) any # later version. # # This library 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 Lesser General Public License for more # details. # # You should have received a copy of the GNU Lesser General Public License # along with pygal. If not, see . """ XY time extensions: handle convertion of date, time, datetime, timedelta into float for xy plot and back to their type for display """ from datetime import date, datetime, time, timedelta from pygal._compat import is_str, timestamp from pygal.adapters import positive from pygal.graph.xy import XY def datetime_to_timestamp(x): """Convert a datetime into a utc float timestamp""" if isinstance(x, datetime): return timestamp(x) return x def datetime_to_time(x): """Convert a datetime into a time""" if isinstance(x, datetime): return x.time() return x def date_to_datetime(x): """Convert a date into a datetime""" if not isinstance(x, datetime) and isinstance(x, date): return datetime.combine(x, time()) return x def time_to_datetime(x): """Convert a time into a datetime""" if isinstance(x, time): return datetime.combine(date(1970, 1, 1), x) return x def timedelta_to_seconds(x): """Convert a timedelta into an amount of seconds""" if isinstance(x, timedelta): return x.total_seconds() return x def time_to_seconds(x): """Convert a time in a seconds sum""" if isinstance(x, time): return (( ((x.hour * 60) + x.minute) * 60 + x.second ) * 10 ** 6 + x.microsecond) / 10 ** 6 if is_str(x): return x # Clamp to valid time return x and max(0, min(x, 24 * 3600 - 10 ** -6)) def seconds_to_time(x): """Convert a number of second into a time""" t = int(x * 10 ** 6) ms = t % 10 ** 6 t = t // 10 ** 6 s = t % 60 t = t // 60 m = t % 60 t = t // 60 h = t return time(h, m, s, ms) class DateTimeLine(XY): """DateTime abscissa xy graph class""" _x_adapters = [datetime_to_timestamp, date_to_datetime] @property def _x_format(self): """Return the value formatter for this graph""" def datetime_to_str(x): dt = datetime.utcfromtimestamp(x) return self.x_value_formatter(dt) return datetime_to_str class DateLine(DateTimeLine): """Date abscissa xy graph class""" @property def _x_format(self): """Return the value formatter for this graph""" def date_to_str(x): d = datetime.utcfromtimestamp(x).date() return self.x_value_formatter(d) return date_to_str class TimeLine(DateTimeLine): """Time abscissa xy graph class""" _x_adapters = [positive, time_to_seconds, datetime_to_time] @property def _x_format(self): """Return the value formatter for this graph""" def date_to_str(x): t = seconds_to_time(x) return self.x_value_formatter(t) return date_to_str class TimeDeltaLine(XY): """TimeDelta abscissa xy graph class""" _x_adapters = [timedelta_to_seconds] @property def _x_format(self): """Return the value formatter for this graph""" def timedelta_to_str(x): td = timedelta(seconds=x) return self.x_value_formatter(td) return timedelta_to_str