Skip to content

Commit

Permalink
updated DATE/DATETIME to also handle datetime inputs and strip away t…
Browse files Browse the repository at this point in the history
…z info, added mission tests
  • Loading branch information
jkminder committed Feb 22, 2022
1 parent f8d315c commit 70dc2d6
Show file tree
Hide file tree
Showing 6 changed files with 82 additions and 3 deletions.
4 changes: 2 additions & 2 deletions docs/documentation.md
Original file line number Diff line number Diff line change
Expand Up @@ -504,9 +504,9 @@ The rel2graph library comes with some predefined wrappers. To use any of them yo
import rel2graph.common_modules
```
- **DATETIME**:
The DATETIME attribute wrapper allows to convert strings into datetime objects. It uses the datetime strptime function to convert the strings to datetime based on some formatting. The default formating string is `"%Y-%m-%dT%H:%M:%S"`. You can provide your own formating string as static argument in the conversion schema: `- datetime = DATETIME(entity.datetime_as_str, "%Y/%m/%d %H:%M:%S")`. Check the [datetime documentation](https://docs.python.org/3/library/datetime.html) for details about how strptime works.
The DATETIME attribute wrapper allows to convert strings into datetime objects. It uses the datetime strptime function to convert the strings to datetime based on some formatting. The default formating string is `"%Y-%m-%dT%H:%M:%S"`. You can provide your own formating string as static argument in the conversion schema: `- datetime = DATETIME(entity.datetime_as_str, "%Y/%m/%d %H:%M:%S")`. If the provided argument is a datetime instead of a string, it will just remove any timezone information. Check the [datetime documentation](https://docs.python.org/3/library/datetime.html) for details about how strptime works.
- **DATE**:
The DATE attribute wrapper allows to convert strings into date objects. It uses the datetime strptime function to convert the strings to datetime based on some formatting and from there into just a date. The default formating string is `"%Y-%m-%d"`. You can provide your own formating string as static argument in the conversion schema: `- date = DATETIME(entity.date_as_str, "%Y/%m/%d %H:%M:%S")`. Check the [datetime documentation](https://docs.python.org/3/library/datetime.html) for details about how strptime works. If the attribute passed to DATE contains also time information, this is simply stripped away (the format string still must fit the exact format of your attribute).
The DATE attribute wrapper allows to convert strings into date objects. It uses the datetime strptime function to convert the strings to datetime based on some formatting and from there into just a date. The default formating string is `"%Y-%m-%d"`. You can provide your own formating string as static argument in the conversion schema: `- date = DATETIME(entity.date_as_str, "%Y/%m/%d %H:%M:%S")`. Check the [datetime documentation](https://docs.python.org/3/library/datetime.html) for details about how strptime works. If the attribute passed to DATE contains also time information, this is simply stripped away (the format string still must fit the exact format of your attribute). If the provided argument is a datetime instead of a string, it will just remove any timezone information and convert it to date.

**Note**: If you encounter the exception `TypeError: Neo4j does not support JSON parameters of type datetime` for the DATE/DATETIME wrappers, make sure that you use the bolt/neo4j scheme with your graph. Dates won't work over *http*:
```g = Graph(scheme="bolt", host="localhost", port=7687, auth=('neo4j', 'password'))```
Expand Down
6 changes: 5 additions & 1 deletion rel2graph/common_modules/util.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,16 @@
"""
from .. import register_attribute_postprocessor
from .. import Attribute
from datetime import datetime, date
from datetime import datetime

@register_attribute_postprocessor
def DATETIME(attribute, format_string="%Y-%m-%dT%H:%M:%S"):
if isinstance(attribute.value, datetime):
return Attribute(attribute.key, attribute.value.replace(tzinfo=None))
return Attribute(attribute.key, datetime.strptime(attribute.value, format_string))

@register_attribute_postprocessor
def DATE(attribute, format_string="%Y-%m-%dT%H:%M:%S"):
if isinstance(attribute.value, datetime):
return Attribute(attribute.key, attribute.value.replace(tzinfo=None).date())
return Attribute(attribute.key, datetime.strptime(attribute.value, format_string).date())
65 changes: 65 additions & 0 deletions tests/unit/common_modules/test_util.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,65 @@
#!/usr/bin/env python
# -*- coding: utf-8 -*-

"""
Tests for OData relational module
TODO: tests heavily access protected members of the library -> improve? how?
authors: Julian Minder
"""

import pytest

from rel2graph.common_modules import util
from rel2graph import Attribute
from datetime import datetime

@pytest.fixture
def default_format():
return Attribute("key", "2015-05-17T21:18:19")

@pytest.fixture
def other_format():
return Attribute("key", "2015/05/17 21h 18min 19s")

@pytest.fixture
def as_datetime():
return Attribute("key", datetime.strptime("2015-05-17T21:18:19", "%Y-%m-%dT%H:%M:%S"))

def test_date(default_format, other_format, as_datetime):
result = util.DATE(default_format).value
assert(result.year == 2015)
assert(result.month == 5)
assert(result.day == 17)
result = util.DATE(other_format, "%Y/%m/%d %Hh %Mmin %Ss").value
assert(result.year == 2015)
assert(result.month == 5)
assert(result.day == 17)
result = util.DATE(as_datetime).value
assert(result.year == 2015)
assert(result.month == 5)
assert(result.day == 17)

def test_datetime(default_format, other_format, as_datetime):
result = util.DATETIME(default_format).value
assert(result.year == 2015)
assert(result.month == 5)
assert(result.day == 17)
assert(result.hour == 21)
assert(result.minute == 18)
assert(result.second == 19)
result = util.DATETIME(other_format, "%Y/%m/%d %Hh %Mmin %Ss").value
assert(result.year == 2015)
assert(result.month == 5)
assert(result.day == 17)
assert(result.hour == 21)
assert(result.minute == 18)
assert(result.second == 19)
result = util.DATETIME(as_datetime).value
assert(result.year == 2015)
assert(result.month == 5)
assert(result.day == 17)
assert(result.hour == 21)
assert(result.minute == 18)
assert(result.second == 19)
8 changes: 8 additions & 0 deletions tests/unit/core/resources/typing.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
ENTITY("entity"):
NODE("node") test:
- mystr = "1" #str
- myfloat = 1.1 #float
- myint = 1 #int
- myTrue = True # bool
- myFalse = False # bool
RELATION(test, "to", MATCH("node", mystr = "1", myint = 1, myfloat = 1.1, myTrue = True, myFalse = False)):
1 change: 1 addition & 0 deletions tests/unit/core/resources/typing_exceptions1.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ENTITY("TEST")
1 change: 1 addition & 0 deletions tests/unit/core/resources/typing_exceptions2.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
ENTITY("TEST")

0 comments on commit 70dc2d6

Please sign in to comment.