Parent: [bd5aaa] (diff)

Child: [11425a] (diff)

Download this file

zarkov_helpers.py    110 lines (93 with data), 4.0 kB

  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
import calendar
from datetime import datetime, timedelta
try:
import zmq
except ImportError:
zmq = None
import bson
class ZarkovClient(object):
def __init__(self, addr):
context = zmq.Context.instance()
self._sock = context.socket(zmq.PUSH)
self._sock.connect(addr)
def event(self, type, context, extra=None):
obj = dict(
type=type, context=context, extra=extra)
self._sock.send(bson.BSON.encode(obj))
def event_noval(self, type, context, extra=None):
from zarkov import model
obj = model.event.make(dict(
type=type,
context=context,
extra=extra))
obj['$command'] = 'event_noval'
self._sock.send(bson.BSON.encode(obj))
def _command(self, cmd, **kw):
d = dict(kw)
d['$command'] = cmd
self._sock.send(bson.BSON.encode(d))
def zero_fill_zarkov_result(zarkov_data, period, start_date, end_date):
"""Return a new copy of zarkov_data (a dict returned from a zarkov
query) with the timeseries data zero-filled for missing dates.
Args:
zarkov_data (dict): A Zarkov query result.
period (str): 'month' or 'date' for monthly or daily timestamps
start_date (datetime or str): Start of the date range. If a str is
passed, it must be in %Y-%m-%d format.
end_date (datetime or str): End of the date range. If a str is
passed, it must be in %Y-%m-%d format.
Returns:
dict. A new copy of zarkov_data, zero-filled.
"""
d = zarkov_data.copy()
if isinstance(start_date, basestring):
start_date = datetime.strptime(start_date, '%Y-%m-%d')
if isinstance(end_date, basestring):
end_date = datetime.strptime(end_date, '%Y-%m-%d')
for query in zarkov_data.iterkeys():
for series in zarkov_data[query].iterkeys():
d[query][series] = zero_fill_time_series(d[query][series],
period, start_date, end_date)
return d
def zero_fill_time_series(time_series, period, start_date, end_date):
"""Return a copy of time_series after adding [timestamp, 0] pairs for
each missing timestamp in the given date range.
Args:
time_series (list): A list of [timestamp, value] pairs, e.g.:
[[1306886400000.0, 1], [1309478400000.0, 0]]
period (str): 'month' or 'date' for monthly or daily timestamps
start_date (datetime or str): Start of the date range. If a str is
passed, it must be in %Y-%m-%d format.
end_date (datetime or str): End of the date range. If a str is
passed, it must be in %Y-%m-%d format.
Returns:
list. A new copy of time_series, zero-filled.
If you want to zero-fill an entire zarkov result, you should use
:func:`zero_fill_zarkov_result` instead, which will call this function
for each timeseries list in the zarkov result.
"""
new_series = dict(time_series)
if period == 'month':
date = start_date
while date <= end_date:
ts = to_utc_timestamp(date)
if ts not in new_series:
new_series[ts] = 0
# next month
if date.month == 12:
date = date.replace(year=date.year+1, month=1)
else:
date = date.replace(month=date.month+1)
else: # daily
days = (end_date - start_date).days + 1
periods = range(0, days)
for dayoffset in periods:
date = start_date + timedelta(days=dayoffset)
ts = to_utc_timestamp(date)
if ts not in new_series:
new_series[ts] = 0
return sorted([[k, v] for k, v in new_series.items()])
def to_utc_timestamp(d):
"""Return UTC unix timestamp representation of d (datetime)."""
# http://stackoverflow.com/questions/1077285/how-to-specify-time-zone-utc-when-converting-to-unix-time-python
return calendar.timegm(d.utctimetuple()) * 1000.0