Source

trac-gviz / trac-dev / gviz / tracgviz / scalar.py

Full commit
#!/usr/bin/env python
# -*- coding: UTF-8 -*-

# Copyright 2009-2011 Olemis Lang <olemis at gmail.com>
#
#   Licensed under the Apache License, Version 2.0 (the "License");
#   you may not use this file except in compliance with the License.
#   You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#   Unless required by applicable law or agreed to in writing, software
#   distributed under the License is distributed on an "AS IS" BASIS,
#   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#   See the License for the specific language governing permissions and
#   limitations under the License.

r"""Scalar functions defined by Google Visualization API (version 7.0)

https://developers.google.com/chart/interactive/docs/querylanguage#scalar_functions

Copyright 2009-2011 Olemis Lang <olemis at gmail.com>
Licensed under the Apache License, Version 2.0 
"""
__author__ = 'Olemis Lang'
__all__ = 'year month day hour minute second millisecond quarter dayOfWeek ' \
    'now dateDiff toDate upper lower'.split()

from datetime import datetime, date, time

def check_datatype(value, types, expected_msg=None):
  if value is None:
    pass
  elif not isinstance(value, types):
    msg = '%s expected but received %s' % (expected_msg, value) \
        if expected_msg else 'Unexpected value %s' % (value,)
    raise ValueError(msg)

def year(value):
  check_datatype(value, (datetime, date), 'Date value')
  return value.year if value is not None else None

year.return_type = 'number'

def month(value):
  check_datatype(value, (datetime, date), 'Date value')
  return value.month - 1 if value is not None else None

month.return_type = 'number'

def day(value):
  check_datatype(value, (datetime, date), 'Date value')
  return value.day if value is not None else None

day.return_type = 'number'

def hour(value):
  check_datatype(value, (time, date), 'Time value')
  return value.hour if value is not None else None

hour.return_type = 'number'

def minute(value):
  check_datatype(value, (time, date), 'Time value')
  return value.minute if value is not None else None

minute.return_type = 'number'

def second(value):
  check_datatype(value, (time, date), 'Time value')
  return value.second if value is not None else None

second.return_type = 'number'

def millisecond(value):
  check_datatype(value, (time, date), 'Time value')
  return value.microsecond / 1000 if value is not None else None

millisecond.return_type = 'number'

def quarter(value):
  return 1 + month(value) / 3 if value is not None else None

quarter.return_type = 'number'

def dayOfWeek(value):
  check_datatype(value, (datetime, date), 'Date value')
  return value.isoweekday() % 7 + 1 if value is not None else None

dayOfWeek.return_type = 'number'

def dateDiff(until, since):
  check_datatype(since, (datetime, date), 'Date value')
  check_datatype(until, (datetime, date), 'Date value')
  return (until - since).days if until is not None and since is not None \
      else None

dateDiff.return_type = 'number'

def now():
  return datetime.now()

now.return_type = 'datetime'
now.deterministic = False

def toDate(value):
  check_datatype(value, (date, datetime, int, long), 'Date value')
  if value is None:
    return None
  if isinstance(value, datetime):
    return value.date()
  elif isinstance(value, date):
    return value
  elif isinstance(value, (int, long)):
    return date.fromtimestamp(value / 1000)
  raise ValueError('Date value expected but received %s' % (value,))

toDate.return_type = 'date'

def upper(value):
  check_datatype(value, basestring, 'String value')
  return value.upper() if value is not None else None

upper.return_type = 'string'

def lower(value):
  check_datatype(value, basestring, 'String value')
  return value.lower() if value is not None else None

lower.return_type = 'string'