diff --git a/mwclient/client.py b/mwclient/client.py
index 8e048f5d63166c640d1a4a5da6ac38aadc54232a..8e11b605508a1d765bde409ee3df0bc68eca86d4 100644
--- a/mwclient/client.py
+++ b/mwclient/client.py
@@ -5,6 +5,7 @@ import sys
 import weakref
 import logging
 from six import text_type
+import six
 
 try:
     # Python 2.7+
@@ -34,12 +35,6 @@ __ver__ = '0.7.2'
 log = logging.getLogger(__name__)
 
 
-def parse_timestamp(t):
-    if t == '0000-00-00T00:00:00Z':
-        return (0, 0, 0, 0, 0, 0, 0, 0)
-    return time.strptime(t, '%Y-%m-%dT%H:%M:%SZ')
-
-
 class WaitToken(object):
 
     def __init__(self):
@@ -125,7 +120,7 @@ class Site(object):
 
         # Extract site info
         self.site = meta['query']['general']
-        self.namespaces = dict(((i['id'], i.get('*', '')) for i in meta['query']['namespaces'].itervalues()))
+        self.namespaces = dict(((i['id'], i.get('*', '')) for i in six.itervalues(meta['query']['namespaces'])))
         self.writeapi = 'writeapi' in self.site
 
         # Determine version
@@ -235,8 +230,8 @@ class Site(object):
     @staticmethod
     def _query_string(*args, **kwargs):
         kwargs.update(args)
-        qs1 = [(k, v) for k, v in kwargs.iteritems() if k not in ('wpEditToken', 'token')]
-        qs2 = [(k, v) for k, v in kwargs.iteritems() if k in ('wpEditToken', 'token')]
+        qs1 = [(k, v) for k, v in six.iteritems(kwargs) if k not in ('wpEditToken', 'token')]
+        qs2 = [(k, v) for k, v in six.iteritems(kwargs) if k in ('wpEditToken', 'token')]
         return OrderedDict(qs1 + qs2)
 
     def raw_call(self, script, data, files=None, retry_on_error=True):
@@ -456,7 +451,7 @@ class Site(object):
                     title = 'Test'
                 info = self.api('query', titles=title,
                                 prop='info', intoken=type)
-                for i in info['query']['pages'].itervalues():
+                for i in six.itervalues(info['query']['pages']):
                     if i['title'] == title:
                         self.tokens[type] = i['%stoken' % type]
 
diff --git a/mwclient/listing.py b/mwclient/listing.py
index 1c83a9ec510fe8ef47712e1b202343cabbefc3ba..e10af951fcb6b353cf5add4c73476a40c2a19122 100644
--- a/mwclient/listing.py
+++ b/mwclient/listing.py
@@ -1,6 +1,7 @@
-import client
 import page
+import six
 from six import text_type
+from mwclient.util import parse_timestamp
 
 
 class List(object):
@@ -31,15 +32,15 @@ class List(object):
     def __iter__(self):
         return self
 
-    def next(self, full=False):
+    def __next__(self, full=False):
         if self.max_items is not None:
             if self.count >= self.max_items:
                 raise StopIteration
         try:
-            item = self._iter.next()
+            item = six.next(self._iter)
             self.count += 1
             if 'timestamp' in item:
-                item['timestamp'] = client.parse_timestamp(item['timestamp'])
+                item['timestamp'] = parse_timestamp(item['timestamp'])
             if full:
                 return item
 
@@ -56,8 +57,12 @@ class List(object):
             self.load_chunk()
             return List.next(self, full=full)
 
+    def next(self, full=False):
+        """ For Python 2.x support """
+        return self.__next__(full)
+
     def load_chunk(self):
-        data = self.site.api('query', (self.generator, self.list_name), *[(text_type(k), v) for k, v in self.args.iteritems()])
+        data = self.site.api('query', (self.generator, self.list_name), *[(text_type(k), v) for k, v in six.iteritems(self.args)])
         if not data:
             # Non existent page
             raise StopIteration
@@ -80,7 +85,7 @@ class List(object):
         elif type(data['query'][self.result_member]) is list:
             self._iter = iter(data['query'][self.result_member])
         else:
-            self._iter = data['query'][self.result_member].itervalues()
+            self._iter = six.itervalues(data['query'][self.result_member])
 
     def __repr__(self):
         return "<List object '%s' for %s>" % (self.list_name, self.site)
@@ -88,7 +93,7 @@ class List(object):
     @staticmethod
     def generate_kwargs(_prefix, *args, **kwargs):
         kwargs.update(args)
-        for key, value in kwargs.iteritems():
+        for key, value in six.iteritems(kwargs):
             if value is not None and value is not False:
                 yield _prefix + key, value
 
@@ -223,7 +228,7 @@ class PageProperty(List):
         self.generator = 'prop'
 
     def set_iter(self, data):
-        for page in data['query']['pages'].itervalues():
+        for page in six.itervalues(data['query']['pages']):
             if page['title'] == self.page.name:
                 self._iter = iter(page.get(self.list_name, ()))
                 return
diff --git a/mwclient/page.py b/mwclient/page.py
index c0c3aec418c34b63340344be707b92a88ae9464e..554536cf38f57b0bea91ecdf074f1d072ee560b8 100644
--- a/mwclient/page.py
+++ b/mwclient/page.py
@@ -1,11 +1,11 @@
-import client
 import errors
 import listing
-
+import six
 from six.moves import urllib
 from six import text_type
 import time
 import warnings
+from mwclient.util import parse_timestamp
 
 
 class Page(object):
@@ -19,9 +19,9 @@ class Page(object):
 
         if not info:
             if extra_properties:
-                prop = 'info|' + '|'.join(extra_properties.iterkeys())
+                prop = 'info|' + '|'.join(six.iterkeys(extra_properties))
                 extra_props = []
-                [extra_props.extend(extra_prop) for extra_prop in extra_properties.itervalues()]
+                [extra_props.extend(extra_prop) for extra_prop in six.itervalues(extra_properties)]
             else:
                 prop = 'info'
                 extra_props = ()
@@ -32,7 +32,7 @@ class Page(object):
             else:
                 info = self.site.api('query', prop=prop, titles=name,
                                      inprop='protection', *extra_props)
-            info = info['query']['pages'].itervalues().next()
+            info = six.next(six.itervalues(info['query']['pages']))
         self._info = info
 
         self.namespace = info.get('ns', 0)
@@ -42,7 +42,7 @@ class Page(object):
         else:
             self.page_title = self.name
 
-        self.touched = client.parse_timestamp(info.get('touched', '0000-00-00T00:00:00Z'))
+        self.touched = parse_timestamp(info.get('touched'))
         self.revision = info.get('lastrevid', 0)
         self.exists = 'missing' not in info
         self.length = info.get('length')
@@ -214,7 +214,7 @@ class Page(object):
 
         # 'newtimestamp' is not included if no change was made
         if 'newtimestamp' in result['edit'].keys():
-            self.last_rev_time = client.parse_timestamp(result['edit'].get('newtimestamp'))
+            self.last_rev_time = parse_timestamp(result['edit'].get('newtimestamp'))
         return result['edit']
 
     def handle_edit_error(self, e, summary):
diff --git a/mwclient/util.py b/mwclient/util.py
new file mode 100644
index 0000000000000000000000000000000000000000..bcd7b60ca8525e85e1afe8ced67ee42f93dd9dc7
--- /dev/null
+++ b/mwclient/util.py
@@ -0,0 +1,7 @@
+import time
+
+
+def parse_timestamp(t):
+    if t is None or t == '0000-00-00T00:00:00Z':
+        return (0, 0, 0, 0, 0, 0, 0, 0, 0)
+    return time.strptime(t, '%Y-%m-%dT%H:%M:%SZ')
diff --git a/tests/test_util.py b/tests/test_util.py
new file mode 100644
index 0000000000000000000000000000000000000000..19e7fa173fae3fc03902e3c7b73a38b8050de0b3
--- /dev/null
+++ b/tests/test_util.py
@@ -0,0 +1,23 @@
+# encoding=utf-8
+from __future__ import print_function
+import unittest
+import time
+from mwclient.util import parse_timestamp
+
+if __name__ == "__main__":
+    print()
+    print("Note: Running in stand-alone mode. Consult the README")
+    print("      (section 'Contributing') for advice on running tests.")
+    print()
+
+
+class TestUtil(unittest.TestCase):
+
+    def test_parse_empty_timestamp(self):
+        assert (0, 0, 0, 0, 0, 0, 0, 0, 0) == parse_timestamp('0000-00-00T00:00:00Z')
+
+    def test_parse_nonempty_timestamp(self):
+        assert time.struct_time([2015, 1, 2, 20, 18, 36, 4, 2, -1]) == parse_timestamp('2015-01-02T20:18:36Z')
+
+if __name__ == '__main__':
+    unittest.main()