Skip to content

Commit

Permalink
Changed format_datetime method to json.
Browse files Browse the repository at this point in the history
Added documentation
  • Loading branch information
jamespeterschinner committed Dec 21, 2017
1 parent dc8d279 commit 1b8fd57
Show file tree
Hide file tree
Showing 18 changed files with 142 additions and 51 deletions.
5 changes: 4 additions & 1 deletion async_v20/definitions/base.py
Original file line number Diff line number Diff line change
Expand Up @@ -231,7 +231,10 @@ def fields():
# to strings when sending JSON data to OANDA
attr = str(attr)
elif isinstance(attr, pd.Timestamp):
attr = attr.format(datetime_format, json=json)
if json or datetime_format == 'RFC3339':
attr = attr.json(datetime_format)
elif datetime_format == 'UNIX':
attr = attr.value

yield field, attr

Expand Down
43 changes: 20 additions & 23 deletions async_v20/definitions/primitives.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,45 +32,42 @@ class DateTime(Primitive):
"""A date and time value using either RFC3339 or UNIX time representation.
"""

def __new__(cls, value):
kwargs = {}
try:
length = len(value)
except TypeError:
def __new__(cls, value, **kwargs):

if not isinstance(value, (int, float, str)):
pass
else:
if length == 20 or isinstance(value, int):
if isinstance(value, str):
value = value.replace('.', '')
value = int(value)
value = str(value)
if len(value) <= 20:
seconds, decimal, fraction = value.partition('.')

if not fraction and len(seconds) > 10:
seconds, fraction = value[:10], value[10:]
# value has decimal number
accuracy = len(fraction)
fraction = fraction + '000000000'[:-accuracy]
value = int(seconds + fraction)
kwargs.update(tz='UTC')

return pd.Timestamp(value, **kwargs)

return pd.Timestamp(value, **kwargs)

def _format_datetime(self, datetime_format, json=False):

if json is True and datetime_format is None:
raise ValueError(f'Must specify datetime_format when creating JSON. Either "RFC3339" or "UNIX"')
def _datetime_to_json(self, datetime_format):

if datetime_format == 'RFC3339':
nanoseconds = str(self.nanosecond)
nanoseconds = nanoseconds + '000'[:-len(nanoseconds)]
result = self.strftime(f'%Y-%m-%dT%H:%M:%S.%f{nanoseconds}Z')
elif datetime_format == 'UNIX':
result = self.value
if json:
result = str(result)
result = f'{result[:-9]}.{result[-9:]}'

elif datetime_format is None:
result = self
result = str(self.value)
result = f'{result[:-9]}.{result[-9:]}'
else:
raise ValueError(f'{datetime_format} is not a valid value. It must be either. None, "RFC3339" or "UNIX"')
return result
raise ValueError(f'{datetime_format} is not a valid value. It must be either "RFC3339" or "UNIX"')

return result

pd.Timestamp.format = _format_datetime
pd.Timestamp.json = _datetime_to_json


class AccountFinancingMode(str, Primitive):
Expand Down
2 changes: 1 addition & 1 deletion async_v20/interface/response.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,7 @@ def value_to_dict(value):
# Specifiers need to be strings for JSON
result = str(value)
elif json and isinstance(value, pd.Timestamp):
result = value.format(datetime_format, json=json)
result = value.json(datetime_format)
else:
result = value
return result
Expand Down
Binary file modified doc/build/doctrees/environment.pickle
Binary file not shown.
Binary file modified doc/build/doctrees/index.doctree
Binary file not shown.
2 changes: 1 addition & 1 deletion doc/build/html/.buildinfo
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
# Sphinx build info version 1
# This file hashes the configuration used when building these files. When it is not found, a full rebuild will be done.
config: 3a3f62cebc4640ab1f6d089856cdbc2a
config: daf7e729f4cdc73e314629963f2f48a2
tags: 645f666f9bcd5a90fca523b33c5a78b7
5 changes: 3 additions & 2 deletions doc/build/html/_modules/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Overview: module code &#8212; async_v20 2.3.0b0 documentation</title>
<title>Overview: module code &#8212; async_v20 4.0.0b0 documentation</title>
<link rel="stylesheet" href="../_static/alabaster.css" type="text/css" />
<link rel="stylesheet" href="../_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: '../',
VERSION: '2.3.0b0',
VERSION: '4.0.0b0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true,
Expand Down Expand Up @@ -74,6 +74,7 @@ <h3>Navigation</h3>
<li class="toctree-l1"><a class="reference internal" href="../best_practices.html">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="../beyond_getting_started.html">Beyond Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="../order_request_formatting.html">Formatting Order Requests</a></li>
<li class="toctree-l1"><a class="reference internal" href="../datetimes.html">Dealing With Time</a></li>
<li class="toctree-l1"><a class="reference internal" href="../traps.html">Traps for young players</a></li>
<li class="toctree-l1"><a class="reference internal" href="../api.html">OandaClient API</a></li>
<li class="toctree-l1"><a class="reference internal" href="../response.html">The Response Object</a></li>
Expand Down
1 change: 1 addition & 0 deletions doc/build/html/_sources/index.rst.txt
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ Contents
best_practices
beyond_getting_started
order_request_formatting
datetimes
traps
api
response
Expand Down
5 changes: 3 additions & 2 deletions doc/build/html/api.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>OandaClient API &#8212; async_v20 2.3.0b0 documentation</title>
<title>OandaClient API &#8212; async_v20 4.0.0b0 documentation</title>
<link rel="stylesheet" href="_static/alabaster.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '2.3.0b0',
VERSION: '4.0.0b0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true,
Expand Down Expand Up @@ -2469,6 +2469,7 @@ <h3>Navigation</h3>
<li class="toctree-l1"><a class="reference internal" href="best_practices.html">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="beyond_getting_started.html">Beyond Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="order_request_formatting.html">Formatting Order Requests</a></li>
<li class="toctree-l1"><a class="reference internal" href="datetimes.html">Dealing With Time</a></li>
<li class="toctree-l1"><a class="reference internal" href="traps.html">Traps for young players</a></li>
<li class="toctree-l1 current"><a class="current reference internal" href="#">OandaClient API</a><ul>
<li class="toctree-l2"><a class="reference internal" href="#oandaclient">OandaClient</a></li>
Expand Down
5 changes: 3 additions & 2 deletions doc/build/html/genindex.html
Original file line number Diff line number Diff line change
Expand Up @@ -6,13 +6,13 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Index &#8212; async_v20 2.3.0b0 documentation</title>
<title>Index &#8212; async_v20 4.0.0b0 documentation</title>
<link rel="stylesheet" href="_static/alabaster.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '2.3.0b0',
VERSION: '4.0.0b0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true,
Expand Down Expand Up @@ -3003,6 +3003,7 @@ <h3>Navigation</h3>
<li class="toctree-l1"><a class="reference internal" href="best_practices.html">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="beyond_getting_started.html">Beyond Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="order_request_formatting.html">Formatting Order Requests</a></li>
<li class="toctree-l1"><a class="reference internal" href="datetimes.html">Dealing With Time</a></li>
<li class="toctree-l1"><a class="reference internal" href="traps.html">Traps for young players</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">OandaClient API</a></li>
<li class="toctree-l1"><a class="reference internal" href="response.html">The Response Object</a></li>
Expand Down
5 changes: 3 additions & 2 deletions doc/build/html/glossary.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Glossary &#8212; async_v20 2.3.0b0 documentation</title>
<title>Glossary &#8212; async_v20 4.0.0b0 documentation</title>
<link rel="stylesheet" href="_static/alabaster.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '2.3.0b0',
VERSION: '4.0.0b0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true,
Expand Down Expand Up @@ -181,6 +181,7 @@ <h3>Navigation</h3>
<li class="toctree-l1"><a class="reference internal" href="best_practices.html">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="beyond_getting_started.html">Beyond Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="order_request_formatting.html">Formatting Order Requests</a></li>
<li class="toctree-l1"><a class="reference internal" href="datetimes.html">Dealing With Time</a></li>
<li class="toctree-l1"><a class="reference internal" href="traps.html">Traps for young players</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">OandaClient API</a></li>
<li class="toctree-l1"><a class="reference internal" href="response.html">The Response Object</a></li>
Expand Down
6 changes: 4 additions & 2 deletions doc/build/html/index.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>async_v20: Asynchronous OANDA v20 client &#8212; async_v20 2.3.0b0 documentation</title>
<title>async_v20: Asynchronous OANDA v20 client &#8212; async_v20 4.0.0b0 documentation</title>
<link rel="stylesheet" href="_static/alabaster.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '2.3.0b0',
VERSION: '4.0.0b0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true,
Expand Down Expand Up @@ -161,6 +161,7 @@ <h2>Contents<a class="headerlink" href="#contents" title="Permalink to this head
</ul>
</li>
<li class="toctree-l1"><a class="reference internal" href="order_request_formatting.html">Formatting Order Requests</a></li>
<li class="toctree-l1"><a class="reference internal" href="datetimes.html">Dealing With Time</a></li>
<li class="toctree-l1"><a class="reference internal" href="traps.html">Traps for young players</a><ul>
<li class="toctree-l2"><a class="reference internal" href="traps.html#error">ERROR!</a></li>
<li class="toctree-l2"><a class="reference internal" href="traps.html#an-order-is-not-an-orderrequest">An Order is not an OrderRequest</a></li>
Expand Down Expand Up @@ -223,6 +224,7 @@ <h3>Navigation</h3>
<li class="toctree-l1"><a class="reference internal" href="best_practices.html">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="beyond_getting_started.html">Beyond Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="order_request_formatting.html">Formatting Order Requests</a></li>
<li class="toctree-l1"><a class="reference internal" href="datetimes.html">Dealing With Time</a></li>
<li class="toctree-l1"><a class="reference internal" href="traps.html">Traps for young players</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">OandaClient API</a></li>
<li class="toctree-l1"><a class="reference internal" href="response.html">The Response Object</a></li>
Expand Down
Binary file modified doc/build/html/objects.inv
Binary file not shown.
5 changes: 3 additions & 2 deletions doc/build/html/search.html
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,13 @@
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Search &#8212; async_v20 2.3.0b0 documentation</title>
<title>Search &#8212; async_v20 4.0.0b0 documentation</title>
<link rel="stylesheet" href="_static/alabaster.css" type="text/css" />
<link rel="stylesheet" href="_static/pygments.css" type="text/css" />
<script type="text/javascript">
var DOCUMENTATION_OPTIONS = {
URL_ROOT: './',
VERSION: '2.3.0b0',
VERSION: '4.0.0b0',
COLLAPSE_INDEX: false,
FILE_SUFFIX: '.html',
HAS_SOURCE: true,
Expand Down Expand Up @@ -90,6 +90,7 @@ <h3>Navigation</h3>
<li class="toctree-l1"><a class="reference internal" href="best_practices.html">Best Practices</a></li>
<li class="toctree-l1"><a class="reference internal" href="beyond_getting_started.html">Beyond Getting Started</a></li>
<li class="toctree-l1"><a class="reference internal" href="order_request_formatting.html">Formatting Order Requests</a></li>
<li class="toctree-l1"><a class="reference internal" href="datetimes.html">Dealing With Time</a></li>
<li class="toctree-l1"><a class="reference internal" href="traps.html">Traps for young players</a></li>
<li class="toctree-l1"><a class="reference internal" href="api.html">OandaClient API</a></li>
<li class="toctree-l1"><a class="reference internal" href="response.html">The Response Object</a></li>
Expand Down
2 changes: 1 addition & 1 deletion doc/build/html/searchindex.js

Large diffs are not rendered by default.

90 changes: 90 additions & 0 deletions doc/source/datetimes.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,90 @@
Dealing With Time
=================

DateTimes in async_20 have a requirement to support two time formats:

- RFC3339 *'2017-08-11T15:04:31.639182000Z'*
- UNIX *'1502463871.639182000'*

.. note::
These are the two valid arguments that may be supplied to :class:`~async_v20.OandaClient`.

:class:`~async_v20.definitions.primitives.DateTime` is responsible for handling datetimes in async_v20
**DateTime** creates *pandas*. **Timestamp**'s from either the RFC3339 or UNIX format.

async_v20 adds an additional helper method *pandas*. *Timestamp*. **json** for the purpose
of serializing to the correct JSON format OANDA expects.

**Serializing**

.. code-block:: python
from async_v20 import DateTime
unix_example = '1502463871.639182000'
rfc3339_example = '2017-08-11T15:04:31.639182000Z'
dt = DateTime(unix_example)
dt
Timestamp('2017-08-11 15:04:31.639182+0000', tz='UTC')
dt.json('RFC3339')
'2017-08-11T15:04:31.639182000Z'
dt.json('UNIX')
'1502463871.639182000'
dt.json('UNIX') == unix_example
True
dt = DateTime(rfc3339_example)
dt.json('UNIX')
'1502463871.639182000'
dt.json('UNIX') == unix_example
True
**Creating from time.time()**

.. code-block:: python
from async_v20 import DateTime
from time import time
dt = DateTime(time())
dt
Timestamp('2017-12-21 01:22:37.762530+0000', tz='UTC')
dt.json('UNIX')
'1513819357.762530000'
dt.json('RFC3339')
'2017-12-21T01:22:37.762530000Z'
**Creating from datetime.datetime.now()**

.. code-block:: python
from async_v20 import DateTime
from datetime import datetime
dt = DateTime(datetime.now())
dt
Timestamp('2017-12-21 12:31:03.982327')
**DataFrame**

.. code-block:: python
from async_v20 import OandaClient
import asyncio
loop = asyncio.get_event_loop()
run = loop.run_until_complete
client = OandaClient()
rsp = run(client.get_candles('EUR_USD'))
df = rsp.candles.dataframe()
df.time[0]
Timestamp('2017-12-20 23:30:40+0000', tz='UTC')
df = rsp.candles.dataframe(datetime_format='RFC3339')
df.time[0]
'2017-12-20T23:30:40.000000000Z'
df = rsp.candles.dataframe(datetime_format='UNIX')
df.time[0]
1513812640000000000
type(df.time[0])
# <class 'numpy.int64'>
df = rsp.candles.dataframe(json=True, datetime_format='UNIX')
df.time[0]
'1513812640.000000000'
type(df.time[0])
# <class 'str'>
1 change: 1 addition & 0 deletions doc/source/index.rst
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,7 @@ Contents
best_practices
beyond_getting_started
order_request_formatting
datetimes
traps
api
response
Expand Down
16 changes: 4 additions & 12 deletions tests/test_definitions/test_primitives.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,23 +14,15 @@ def test_datetime_converts_between_different_representations():
unix_example = '1502463871.639182000'
rfc3339_example = '2017-08-11T15:04:31.639182000Z'
assert DateTime(unix_example) == DateTime(rfc3339_example)
assert DateTime(rfc3339_example).format('UNIX', json=True) == unix_example
assert DateTime(rfc3339_example).format('UNIX') == int(unix_example.replace('.', ''))
assert DateTime(DateTime(rfc3339_example).format('UNIX', json=True)) == DateTime(rfc3339_example)
assert DateTime(unix_example).format('RFC3339') == rfc3339_example
assert DateTime(rfc3339_example).json('UNIX') == unix_example
assert DateTime(DateTime(rfc3339_example).json('UNIX')) == DateTime(rfc3339_example)
assert DateTime(unix_example).json('RFC3339') == rfc3339_example

def test_datetime_format_does_not_allow_json_with_no_format_string():
unix_example = '1502463871.639182000'
with pytest.raises(TypeError):
assert DateTime(unix_example).format(json=True)

with pytest.raises(ValueError):
assert DateTime(unix_example).format(datetime_format=None, json=True)

def test_datetime_format_only_allows_valid_format_string():
unix_example = '1502463871.639182000'
with pytest.raises(ValueError):
assert DateTime(unix_example).format(datetime_format='BADVALUE')
assert DateTime(unix_example).json(datetime_format='BADVALUE')

@pytest.mark.parametrize('primitive', map(lambda x: getattr(primitives, x), primitives.__all__))
def test_get_valid_primitive_data(primitive):
Expand Down

0 comments on commit 1b8fd57

Please sign in to comment.