Browse Source

added support for wienerlinien single tickets

Fabian Peter Hammerle 7 years ago
parent
commit
f0f857c11a
7 changed files with 408 additions and 257 deletions
  1. 79 8
      dingguo/__init__.py
  2. 80 0
      dingguo/parser/wienerlinien.py
  3. 4 1
      setup.py
  4. 24 0
      tests/test_.py
  5. 45 62
      tests/test_comparison.py
  6. 24 0
      tests/test_parser_wienerlinien.py
  7. 152 186
      tests/test_yaml.py

+ 79 - 8
dingguo/__init__.py

@@ -1,5 +1,7 @@
 # -*- coding: utf-8 -*-
 
+import re
+import pytz
 import yaml
 import yaml.representer
 import datetime
@@ -11,6 +13,18 @@ yaml.Loader.add_constructor(
     lambda loader, node: unicode(loader.construct_scalar(node)),
     )
 
+def yaml_construct_timestamp(loader, node):
+    loaded_dt = loader.construct_yaml_timestamp(node)
+    if type(loaded_dt) is datetime.datetime and loaded_dt.tzinfo is None:
+        timezone_match = re.search(
+            ur'\+(?P<h>\d{2}):(?P<m>\d{2})$',
+            loader.construct_python_unicode(node),
+            )
+        if timezone_match:
+            loaded_dt = loaded_dt.replace(tzinfo = pytz.utc)
+    return loaded_dt
+yaml.Loader.add_constructor(u'tag:yaml.org,2002:timestamp', yaml_construct_timestamp)
+
 class _YamlInitConstructor(yaml.YAMLObject):
 
     @classmethod
@@ -357,18 +371,31 @@ class Transportation(Item):
             departure_point = None,
             destination_point = None,
             distance = None,
+            passenger = None,
             route_map = None,
+            valid_from = None,
             **kwargs
             ):
         super(Transportation, self).__init__(**kwargs)
-        assert type(departure_point) is unicode
-        self.departure_point = departure_point
-        assert type(destination_point) is unicode
-        self.destination_point = destination_point
-        assert distance is None or type(distance) is Distance
-        self.distance = distance
-        assert route_map is None or type(route_map) is str
-        self.route_map = route_map
+        if departure_point is not None:
+            assert type(departure_point) is unicode
+            self.departure_point = departure_point
+        if destination_point is not None:
+            assert type(destination_point) is unicode
+            self.destination_point = destination_point
+        if distance is not None:
+            assert type(distance) is Distance
+            self.distance = distance
+        if route_map is not None:
+            assert type(route_map) is str
+            self.route_map = route_map
+        if passenger is not None:
+            assert type(passenger) is Person
+            self.passenger = passenger
+        if valid_from is not None:
+            assert type(valid_from) is datetime.datetime
+            assert not valid_from.tzinfo is None
+            self.valid_from = valid_from
 
     def dict_repr(self):
         attr = super(Transportation, self).dict_repr()
@@ -439,3 +466,47 @@ class OrderRegistry(yaml.YAMLObject):
 
     def __ne__(self, other):
         return not self == other
+
+class Person(_YamlInitConstructor):
+
+    yaml_tag = u'!person'
+
+    def __init__(self, first_name = None, last_name = None):
+        self.first_name = first_name
+        self.last_name = last_name
+
+    @property
+    def first_name(self):
+        return self._first_name
+
+    @first_name.setter
+    def first_name(self, first_name):
+        assert first_name is None or type(first_name) is unicode
+        self._first_name = first_name
+
+    @property
+    def last_name(self):
+        return self._last_name
+
+    @last_name.setter
+    def last_name(self, last_name):
+        assert last_name is None or type(last_name) is unicode
+        self._last_name = last_name
+
+    @classmethod
+    def to_yaml(cls, dumper, person):
+        return dumper.represent_mapping(cls.yaml_tag, {
+            'first_name': person.first_name,
+            'last_name': person.last_name,
+            })
+
+    def __eq__(self, other):
+        return type(self) == type(other) and vars(self) == vars(other)
+
+    def __ne__(self, other):
+        return not self == other
+
+    def __repr__(self):
+        return self.__class__.__name__ + '(%s)' % ', '.join([
+            '%s=%r' % (k, v) for k, v in vars(self).items()
+            ])

+ 80 - 0
dingguo/parser/wienerlinien.py

@@ -0,0 +1,80 @@
+# -*- coding: utf-8 -*-
+
+import datetime
+import dingguo
+import email
+import email.utils
+import ioex
+import re
+
+class UtcOffsetTimezone(datetime.tzinfo):
+
+    def __init__(self, seconds):
+        assert type(seconds) is int
+        self.seconds = seconds
+
+    def utcoffset(self, dt):
+        return datetime.timedelta(seconds = self.seconds)
+
+    def dst(self, dt):
+        return None
+
+    def tzname(self, dt):
+        return self.__class__.__name__ + '(seconds = %d)' % self.seconds
+
+def parse_order_confirmation_mail(mail):
+
+    assert isinstance(mail, email.message.Message)
+
+    msg_text = mail.get_payload(decode = True).decode('utf8')
+    if not 'Wiener Linien' in msg_text:
+        raise Exception()
+
+    order_match = re.search(
+        r'(?P<name>Single-Ticket)\s+'
+            + r'Valid from: (?P<valid_from>\d{1,2} \w+ \d{4} \d{1,2}:\d{2})\s+'
+            + r'Type: (?P<type>Mobile ticket)\s+'
+            + r'For\:\s+'
+            + r'(?P<passenger_first_name>Fabian Peter)\s+'
+            + r'(?P<passenger_last_name>Hammerle)\s+'
+            + ur'Price: (?P<currency>€)(?P<price>2.80)\s+'
+            + r'Quantity: (?P<quantity>1)\s+'
+            ,
+        msg_text,
+        re.MULTILINE | re.UNICODE
+        )
+    if not order_match:
+        print(repr(msg_text))
+    order_match_groups = order_match.groupdict()
+
+    email_recipient_address = mail['delivered-to'].decode('utf8')
+    email_date = datetime.datetime.utcfromtimestamp(
+        # seconds since the Epoch in UTC
+        email.utils.mktime_tz(email.utils.parsedate_tz(mail['date']))
+        )
+    order = dingguo.Order(
+        platform = u'wiener_linien',
+        order_id = '%s-%s' % (email_recipient_address, email_date.isoformat()),
+        order_date = email_date,
+        customer_id = email_recipient_address,
+        )
+
+    assert int(order_match_groups['quantity']) == 1
+
+    with ioex.setlocale('en_US.UTF-8'):
+        import pytz
+        order.items.append(dingguo.Transportation(
+            name = order_match_groups['name'],
+            price_brutto = dingguo.Sum(
+                float(order_match_groups['price']),
+                order_match_groups['currency'],
+                ),
+            passenger = dingguo.Person(
+                first_name = order_match_groups['passenger_first_name'],
+                last_name = order_match_groups['passenger_last_name'],
+                ),
+            valid_from = datetime.datetime.strptime(order_match_groups['valid_from'], '%d %B %Y %H:%M')
+                .replace(tzinfo = UtcOffsetTimezone(email.utils.parsedate_tz(mail['date'])[9]))
+            ))
+
+    return [order]

+ 4 - 1
setup.py

@@ -17,6 +17,9 @@ setup(
         'dingguo.parser',
         ],
     scripts = glob.glob('scripts/*'),
-    install_requires = ['pdfminer>=20140328'],
+    install_requires = [
+        'pdfminer>=20140328', 
+        'pytz',
+        ],
     tests_require = ['pytest'],
     )

+ 24 - 0
tests/test_.py

@@ -15,3 +15,27 @@ def test_sum_init_usd():
 
 def test_distance_metres():
     assert int(dingguo.Distance(1.23, u'km').metres) == 1230
+
+def test_person_first_name():
+    p = dingguo.Person()
+    p.first_name = u'äbc'
+    assert p.first_name == u'äbc'
+    p.first_name = u'qrßtuvw'
+    assert p.first_name == u'qrßtuvw'
+
+def test_person_first_name_string():
+    p = dingguo.Person()
+    with pytest.raises(Exception):
+        p.first_name = 'äbc'
+
+def test_person_last_name():
+    p = dingguo.Person()
+    p.last_name = u'歌曲'
+    assert p.last_name == u'歌曲'
+    p.last_name = u'bär'
+    assert p.last_name == u'bär'
+
+def test_person_last_name_string():
+    p = dingguo.Person()
+    with pytest.raises(Exception):
+        p.last_name = 'äbc'

+ 45 - 62
tests/test_comparison.py

@@ -69,68 +69,51 @@ def get_order_c():
     order.discounts.append(get_discount_b())
     return order
 
-def test_figure_eq():
-    assert dingguo.Figure(1, u'mm') == dingguo.Figure(1, u'mm')
-
-def test_figure_eq_inverted():
-    assert not dingguo.Figure(1, u'mm') == dingguo.Figure(2, u'mm')
-
-def test_figure_ne():
-    assert dingguo.Figure(1, u'mm') != dingguo.Figure(2, u'mm')
-
-def test_figure_ne_inverted():
-    assert not dingguo.Figure(1, u'mm') != dingguo.Figure(1, u'mm')
-
-def test_item_eq():
-    assert get_item_a() == get_item_a()
-    assert get_item_b() == get_item_b()
-
-def test_item_eq_inverted():
-    assert not get_item_a() == get_item_b()
-
-def test_item_ne():
-    assert get_item_a() != get_item_b()
-
-def test_item_ne_inverted():
-    assert not get_item_a() != get_item_a()
-    assert not get_item_b() != get_item_b()
-
-def test_discount_eq():
-    assert get_discount_a() == get_discount_a()
-    assert get_discount_b() == get_discount_b()
-
-def test_discount_eq_inverted():
-    assert not get_discount_a() == get_discount_b()
-
-def test_discount_ne():
-    assert get_discount_a() != get_discount_b()
-
-def test_discount_ne_inverted():
-    assert not get_discount_a() != get_discount_a()
-    assert not get_discount_b() != get_discount_b()
-
-def test_order_eq():
-    assert get_order_a() == get_order_a()
-    assert get_order_b() == get_order_b()
-    assert get_order_c() == get_order_c()
-
-def test_order_eq_inverted():
-    assert not get_order_a() == get_order_c()
-    assert not get_order_b() == get_order_a()
-    assert not get_order_c() == get_order_b()
-
-def test_order_ne():
-    assert get_order_a() != get_order_c()
-    assert get_order_b() != get_order_a()
-    assert get_order_c() != get_order_b()
-
-def test_order_ne_inverted():
-    assert not get_order_a() != get_order_a()
-    assert not get_order_b() != get_order_b()
-    assert not get_order_c() != get_order_c()
-
-def test_order_ne_items():
-    assert get_order_a() != get_order_a(items = False)
+def get_person_a():
+    return dingguo.Person(
+        first_name = u'Fabian Peter',
+        last_name = u'Hammerle',
+        )
+
+def get_person_b():
+    return dingguo.Person(
+        first_name = u'名字',
+        last_name = u'贵姓',
+        )
+
+@pytest.mark.parametrize('a,b', [
+    [dingguo.Figure(1, u'mm'), dingguo.Figure(1, u'mm')],
+    [get_item_a(), get_item_a()],
+    [get_item_b(), get_item_b()],
+    [get_person_a(), get_person_a()],
+    [get_person_b(), get_person_b()],
+    [get_discount_a(), get_discount_a()],
+    [get_discount_b(), get_discount_b()],
+    [get_order_a(), get_order_a()],
+    [get_order_b(), get_order_b()],
+    [get_order_c(), get_order_c()],
+    ])
+def test_eq(a, b):
+    assert a == b
+    assert b == a
+    assert not a != b
+    assert not b != a
+
+@pytest.mark.parametrize('a,b', [
+    [dingguo.Figure(1, u'mm'), dingguo.Figure(2, u'mm')],
+    [get_item_a(), get_item_b()],
+    [get_person_a(), get_person_b()],
+    [get_discount_a(), get_discount_b()],
+    [get_order_a(), get_order_b()],
+    [get_order_a(), get_order_a(items = False)],
+    [get_order_b(), get_order_c()],
+    [get_order_a(), get_order_c()],
+    ])
+def test_neq(a, b):
+    assert a != b
+    assert b != a
+    assert not a == b
+    assert not b == a
 
 def test_order_ne_items_reversed():
     order = get_order_a()

+ 24 - 0
tests/test_parser_wienerlinien.py

@@ -0,0 +1,24 @@
+# -*- coding: utf-8 -*-
+
+import pytest
+
+import dingguo.parser.wienerlinien
+import email
+import glob
+import os
+import test_yaml
+import yaml
+
+project_root_path = os.path.realpath(os.path.join(__file__, '..', '..'))
+test_data_path = os.path.join(project_root_path, 'tests', 'data', 'wienerlinien')
+
+@pytest.mark.parametrize('mail_path', glob.glob(os.path.join(test_data_path, '*.eml')))
+def test_parse_confirmation_mail(mail_path):
+    with open(mail_path) as mail:
+        parsed_orders = dingguo.parser.wienerlinien.parse_order_confirmation_mail(
+                email.message_from_file(mail)
+                )
+    with open(mail_path.replace('.eml', '.yml')) as yaml_file:
+        expected_orders = yaml.load(yaml_file.read())
+    assert expected_orders == parsed_orders, \
+            test_yaml.yaml_diff(expected_orders, parsed_orders)

+ 152 - 186
tests/test_yaml.py

@@ -3,6 +3,7 @@
 import pytest
 
 import os
+import pytz
 import yaml
 import dingguo
 import difflib
@@ -32,6 +33,18 @@ def get_item_b():
             price_brutto = get_sum_b(),
             )
 
+def get_person_a():
+    return dingguo.Person(
+        first_name = u'Fabian Peter',
+        last_name = u'Hammerle',
+        )
+
+def get_person_b():
+    return dingguo.Person(
+        first_name = u'名字',
+        last_name = u'贵姓',
+        )
+
 def get_article():
     return dingguo.Article(
             authors = ['a', 'b'],
@@ -56,6 +69,8 @@ def get_transportation():
             departure_point = u'home',
             destination_point = u'city',
             distance = dingguo.Distance(3.21, u'km'),
+            passenger = get_person_a(),
+            valid_from = datetime.datetime(2016, 7, 14, 13, 50, 4, 0, tzinfo = pytz.timezone('Europe/Vienna')), 
             )
 
 def get_taxi_ride():
@@ -66,8 +81,8 @@ def get_taxi_ride():
             destination_point = u'city',
             distance = dingguo.Distance(3.21, u'km'),
             driver = u'driver',
-            arrival_time = datetime.datetime(2016, 5, 2, 18, 10),
-            departure_time = datetime.datetime(2016, 5, 2, 18, 25),
+            arrival_time = datetime.datetime(2016, 5, 2, 18, 10, tzinfo = pytz.timezone('Europe/Vienna')),
+            departure_time = datetime.datetime(2016, 5, 2, 18, 25, tzinfo = pytz.timezone('Europe/Vienna')),
             )
 
 def get_discount_a():
@@ -133,95 +148,23 @@ def yaml_diff(a, b):
         to_yaml(b).split('\n'),
         ))
 
-def test_figure_to_yaml():
-    assert to_yaml(get_figure_a()) == u"""!figure
-unit: km
-value: 12.3
-"""
-
-def test_figure_to_yaml_unicode():
-    assert to_yaml(get_figure_b()) == u"""!figure
-unit: 米
-value: 12300
-"""
-
-def test_figure_from_yaml():
-    assert get_figure_a() == yaml.load(u"""!figure
-unit: km
-value: 12.3
-""")
-
-def test_figure_to_yaml_unicode():
-    assert get_figure_b() == yaml.load(u"""!figure
-unit: 米
-value: 12300
-""")
-
-def test_sum_to_yaml_a():
-    assert to_yaml(get_sum_a()) == u"!sum '1.23 EUR'\n"
-
-def test_sum_to_yaml_b():
-    assert to_yaml(get_sum_b()) == u"!sum '20.45 EUR'\n"
-
-def test_sum_from_yaml_a():
-    assert get_sum_a() == yaml.load(u"!sum 1.23 EUR")
-
-def test_sum_from_yaml_a_sign():
-    assert get_sum_a() == yaml.load(u"!sum 1.23 €")
-
-def test_sum_from_yaml_a_quotes():
-    assert get_sum_a() == yaml.load(u"!sum '1.23 EUR'")
-
-def test_item_to_yaml_a():
-    assert to_yaml(get_item_a()) == u"""!item
-name: item a
-price_brutto: !sum '1.23 EUR'
-"""
-
-def test_item_to_yaml_b():
-    assert to_yaml(get_item_b()) == u"""!item
-name: item β
-price_brutto: !sum '20.45 EUR'
-"""
-
-def test_item_from_yaml_a():
-    assert get_item_a() == yaml.load(u"""!item
-name: item a
-price_brutto: !sum '1.23 EUR'
-""")
-
-def test_item_from_yaml_b():
-    assert get_item_b() == yaml.load(u"""!item
-name: item β
-price_brutto: !sum '20.45 EUR'
-""")
-
-def test_discount_to_yaml_a():
-    assert to_yaml(get_discount_a()) == u"""!discount
-amount: !sum '1.23 EUR'
-name: discount a
-"""
-
-def test_discount_to_yaml_b():
-    assert to_yaml(get_discount_b()) == u"""!discount
-amount: !sum '20.45 EUR'
-name: discount β
-"""
-
-def test_discount_from_yaml_a():
-    assert get_discount_a() == yaml.load(u"""!discount
-name: discount a
-amount: !sum '1.23 EUR'
-""")
-
-def test_discount_from_yaml_b():
-    assert get_discount_b() == yaml.load(u"""!discount
-name: discount β
-amount: !sum '20.45 EUR'
-""")
-
-def test_order_to_yaml():
-    assert to_yaml(get_order_a()) == u"""!order
+@pytest.mark.parametrize('source_object,expected_yaml', [
+    [datetime.datetime(2016, 7, 14, 13, 50, 4, 0), '2016-07-14 13:50:04\n...\n'],
+    [datetime.datetime(2016, 7, 14, 13, 50, 4, 0, tzinfo = pytz.timezone('Europe/Vienna')), '2016-07-14 13:50:04+01:05\n...\n'],
+    [datetime.datetime(2016, 7, 14, 13, 50, 4, 0, tzinfo = pytz.utc), '2016-07-14 13:50:04+00:00\n...\n'],
+    [dingguo.Distance(1.34, u'km'), u"!distance '1.34 km'\n"],
+    [dingguo.ScalarFigure(1.34, u'μm'), u"!scalar '1.34 μm'\n"],
+    [get_discount_a(), u"!discount\namount: !sum '1.23 EUR'\nname: discount a\n"],
+    [get_discount_b(), u"!discount\namount: !sum '20.45 EUR'\nname: discount β\n"],
+    [get_figure_a(), u'!figure\nunit: km\nvalue: 12.3\n'],
+    [get_figure_b(), u'!figure\nunit: 米\nvalue: 12300\n'],
+    [get_item_a(), u"!item\nname: item a\nprice_brutto: !sum '1.23 EUR'\n"],
+    [get_item_b(), u"!item\nname: item β\nprice_brutto: !sum '20.45 EUR'\n"],
+    [get_person_a(), u'!person\nfirst_name: Fabian Peter\nlast_name: Hammerle\n'],
+    [get_person_b(), u'!person\nfirst_name: 名字\nlast_name: 贵姓\n'],
+    [get_sum_a(), u"!sum '1.23 EUR'\n"],
+    [get_sum_b(), u"!sum '20.45 EUR'\n"],
+    [get_order_a(), u"""!order
 customer_id: customer
 discounts:
 - !discount
@@ -240,7 +183,122 @@ items:
 order_date: 2016-05-08
 order_id: id
 platform: platformπ
-"""
+"""],
+    [get_article(), u"""!article
+authors:
+- a
+- b
+delivery_date: null
+depth: !scalar '12.3 dm'
+features: supergeil
+height: !scalar '123.0 cm'
+maximum_load: !scalar '40.0 kg'
+name: article name
+price_brutto: !sum '1.23 EUR'
+product_id: 0815
+quantity: 1
+reseller: seller
+shipper: shipper
+state: goood
+width: !scalar '1.23 m'
+"""],
+    [get_transportation(), u"""!transportation
+departure_point: home
+destination_point: city
+distance: !distance '3.21 km'
+name: ticket
+passenger: !person
+  first_name: Fabian Peter
+  last_name: Hammerle
+price_brutto: !sum '1.23 EUR'
+valid_from: 2016-07-14 13:50:04+01:05
+"""],
+    [get_taxi_ride(), u"""!taxi-ride
+arrival_time: 2016-05-02 18:10:00+01:05
+departure_point: home
+departure_time: 2016-05-02 18:25:00+01:05
+destination_point: city
+distance: !distance '3.21 km'
+driver: driver
+name: taxi ride
+price_brutto: !sum '1.23 EUR'
+"""],
+    [get_order_registry(), u"""!order-registry
+platformπ:
+  id: !order
+    customer_id: customer
+    discounts: []
+    items: []
+    order_date: 2016-05-08
+    order_id: id
+    platform: platformπ
+  order_b: !order
+    customer_id: null
+    discounts: []
+    items: []
+    order_date: 2015-05-08
+    order_id: order_b
+    platform: platformπ
+γάμμα:
+  order_βήτα: !order
+    customer_id: ρώ
+    discounts: []
+    items: []
+    order_date: 2014-05-08
+    order_id: order_βήτα
+    platform: γάμμα
+"""],
+    ])
+def test_to_yaml(source_object, expected_yaml):
+    assert to_yaml(source_object) == expected_yaml
+
+@pytest.mark.parametrize('expected_object,source_yaml', [
+    [datetime.datetime(2016, 7, 14, 13, 50, 4, 0), '2016-07-14 13:50:04'],
+    [datetime.datetime(2016, 7, 14, 13, 50, 4, 0, tzinfo = pytz.timezone('Europe/Vienna')), '2016-07-14 13:50:04+01:05'],
+    [datetime.datetime(2016, 7, 14, 13, 50, 4, 0, tzinfo = pytz.utc), '2016-07-14 13:50:04+00:00'],
+    [dingguo.Distance(1.34, u'km'), u"!distance '1.34 km'\n"],
+    [dingguo.ScalarFigure(1.34, u'μm'), u"!scalar '1.34 μm'"],
+    [get_discount_a(), u"!discount\nname: discount a\namount: !sum '1.23 EUR'\n"],
+    [get_discount_b(), u"!discount\nname: discount β\namount: !sum '20.45 EUR'\n"],
+    [get_figure_a(), '!figure\nunit: km\nvalue: 12.3\n'],
+    [get_figure_a(), u'!figure\nunit: km\nvalue: 12.3\n'],
+    [get_figure_b(), '!figure\nunit: 米\nvalue: 12300\n'],
+    [get_figure_b(), u'!figure\nunit: 米\nvalue: 12300\n'],
+    [get_item_a(), u"!item\nname: item a\nprice_brutto: !sum '1.23 EUR'\n"],
+    [get_item_a(), u"!item\nname: item a\nprice_brutto: !sum 1.23 EUR"],
+    [get_item_a(), u"!item\nname: item a\nprice_brutto: !sum 1.23 €\n"],
+    [get_item_b(), u"!item\nname: item β\nprice_brutto: !sum '20.45 EUR'\n"],
+    [get_person_a(), '!person\nfirst_name: Fabian Peter\nlast_name: Hammerle\n'],
+    [get_person_a(), u'!person\nfirst_name: Fabian Peter\nlast_name: Hammerle\n'],
+    [get_person_b(), u'!person\nfirst_name: 名字\nlast_name: 贵姓\n'],
+    [get_sum_a(), "!sum 1.23 €"],
+    [get_sum_a(), u"!sum '1.23 EUR'"],
+    [get_sum_a(), u"!sum '1.23 EUR'"],
+    [get_sum_a(), u"!sum 1.23 EUR"],
+    [get_sum_a(), u"!sum 1.23 €"],
+    [[get_person_a(), get_person_b()], u"""
+- !person
+  first_name: Fabian Peter
+  last_name: Hammerle
+- !person
+  first_name: 名字
+  last_name: 贵姓"""],
+    [get_transportation(), u"""!transportation
+departure_point: home
+destination_point: city
+distance: !distance '3.21 km'
+name: ticket
+price_brutto: !sum '1.23 EUR'
+route_map: null
+passenger: !person
+  first_name: Fabian Peter
+  last_name: Hammerle
+valid_from: 2016-07-14 13:50:04+01:05
+"""],
+    ])
+def test_from_yaml(expected_object, source_yaml):
+    loaded_object = yaml.load(source_yaml)
+    assert loaded_object == expected_object
 
 def test_order_from_yaml():
     order_loaded = yaml.load(u"""!order
@@ -266,38 +324,6 @@ platform: platformπ
     order_expected = get_order_a()
     assert order_expected == order_loaded, yaml_diff(order_expected, order_loaded)
 
-def test_scalar_figure_to_yaml():
-    assert to_yaml(dingguo.ScalarFigure(1.34, u'μm')) == u"!scalar '1.34 μm'\n"
-
-def test_scalar_figure_from_yaml():
-    assert dingguo.ScalarFigure(1.34, u'μm') == yaml.load(u"!scalar '1.34 μm'")
-
-def test_distance_to_yaml():
-    assert to_yaml(dingguo.Distance(1.34, u'km')) == u"!distance '1.34 km'\n"
-
-def test_distance_from_yaml():
-    assert dingguo.Distance(1.34, u'km') == yaml.load(u"!distance '1.34 km'\n")
-
-def test_article_to_yaml():
-    assert to_yaml(get_article()) == u"""!article
-authors:
-- a
-- b
-delivery_date: null
-depth: !scalar '12.3 dm'
-features: supergeil
-height: !scalar '123.0 cm'
-maximum_load: !scalar '40.0 kg'
-name: article name
-price_brutto: !sum '1.23 EUR'
-product_id: 0815
-quantity: 1
-reseller: seller
-shipper: shipper
-state: goood
-width: !scalar '1.23 m'
-"""
-
 def test_article_from_yaml():
     assert get_article() == yaml.load(u"""!article
 authors:
@@ -318,44 +344,11 @@ maximum_load: !scalar 40.0 kg
 width: !scalar 1.23 m
 """)
 
-def test_transportation_to_yaml():
-    assert to_yaml(get_transportation()) == u"""!transportation
-departure_point: home
-destination_point: city
-distance: !distance '3.21 km'
-name: ticket
-price_brutto: !sum '1.23 EUR'
-route_map: null
-"""
-
-def test_transportation_from_yaml():
-    assert get_transportation() == yaml.load(u"""!transportation
-departure_point: home
-destination_point: city
-distance: !distance '3.21 km'
-name: ticket
-price_brutto: !sum '1.23 EUR'
-route_map: null
-""")
-
-def test_taxi_ride_to_yaml():
-    assert to_yaml(get_taxi_ride()) == u"""!taxi-ride
-arrival_time: 2016-05-02 18:10:00
-departure_point: home
-departure_time: 2016-05-02 18:25:00
-destination_point: city
-distance: !distance '3.21 km'
-driver: driver
-name: taxi ride
-price_brutto: !sum '1.23 EUR'
-route_map: null
-"""
-
 def test_taxi_ride_from_yaml():
     assert get_taxi_ride() == yaml.load(u"""!taxi-ride
-arrival_time: 2016-05-02 18:10:00
+arrival_time: 2016-05-02 18:10:00+01:05
 departure_point: home
-departure_time: 2016-05-02 18:25:00
+departure_time: 2016-05-02 18:25:00+01:05
 destination_point: city
 distance: !distance '3.21 km'
 driver: driver
@@ -364,33 +357,6 @@ price_brutto: !sum '1.23 EUR'
 route_map: null
 """)
 
-def test_order_registry_to_yaml():
-    assert to_yaml(get_order_registry()) == u"""!order-registry
-platformπ:
-  id: !order
-    customer_id: customer
-    discounts: []
-    items: []
-    order_date: 2016-05-08
-    order_id: id
-    platform: platformπ
-  order_b: !order
-    customer_id: null
-    discounts: []
-    items: []
-    order_date: 2015-05-08
-    order_id: order_b
-    platform: platformπ
-γάμμα:
-  order_βήτα: !order
-    customer_id: ρώ
-    discounts: []
-    items: []
-    order_date: 2014-05-08
-    order_id: order_βήτα
-    platform: γάμμα
-"""
-
 def test_order_registry_from_yaml():
     expected = get_order_registry()
     loaded = yaml.load(u"""!order-registry