diff -r 5754f069b123 Include/datetime.h
--- a/Include/datetime.h	Sat Nov 22 12:54:57 2014 -0800
+++ b/Include/datetime.h	Tue Dec 16 09:04:35 2014 -0800
@@ -18,18 +18,34 @@
  *  5           minute   1 byte, 0-59
  *  6           second   1 byte, 0-59
  *  7           usecond  3 bytes, 0-999999
- * 10
+ * 10           nsecond  2 bytes, 0-999
+ * 12
  */
 
 /* # of bytes for year, month, and day. */
 #define _PyDateTime_DATE_DATASIZE 4
 
-/* # of bytes for hour, minute, second, and usecond. */
-#define _PyDateTime_TIME_DATASIZE 6
+/* # of bytes for hour, minute, second, usecond and nsecond. */
+#define _PyDateTime_TIME_DATASIZE 8
+#define _PyDateTime_TIME_DATASIZE_V0 6 /* older version used for backward compatibility access */
 
-/* # of bytes for year, month, day, hour, minute, second, and usecond. */
-#define _PyDateTime_DATETIME_DATASIZE 10
+/* # of bytes for year, month, day, hour, minute, second, usecond and nsecond. */
+#define _PyDateTime_DATETIME_DATASIZE 12
+#define _PyDateTime_DATETIME_DATASIZE_V0 10 /* older version used for backward compatibility access */
 
+/* max usecond is hex(1e6) = 0x0f4240, hence the 4 upper bits that are not used to encode the
+ * number of milliseconds can be used for pickle versioning.
+ */
+#define _PyDateTime_USECOND_MSB_VALUE_MASK 0x0f
+#define _PyDateTime_USECOND_MSB_PICKLEVERSION_MASK 0xf0
+/* up to 15 pickle versions are available
+ * version 0 is vanilla
+ * version 1 adds nanosecond (this version)
+ * version 2..15 are available for future upgrades
+ */
+#define _PyDateTime_PICKLE_V0_VANILLA 0
+#define _PyDateTime_PICKLE_V1_NANOSECOND 1
+#define _PyDateTime_PICKLE_CURRENT_VERSION _PyDateTime_PICKLE_V1_NANOSECOND
 
 typedef struct
 {
@@ -38,6 +54,7 @@
     int days;                   /* -MAX_DELTA_DAYS <= days <= MAX_DELTA_DAYS */
     int seconds;                /* 0 <= seconds < 24*3600 is invariant */
     int microseconds;           /* 0 <= microseconds < 1000000 is invariant */
+    int nanoseconds;            /* 0 <= nanoseconds < 1000 is invariant */
 } PyDateTime_Delta;
 
 typedef struct
@@ -122,18 +139,30 @@
 #define PyDateTime_DATE_GET_MINUTE(o)      (((PyDateTime_DateTime*)o)->data[5])
 #define PyDateTime_DATE_GET_SECOND(o)      (((PyDateTime_DateTime*)o)->data[6])
 #define PyDateTime_DATE_GET_MICROSECOND(o)              \
-    ((((PyDateTime_DateTime*)o)->data[7] << 16) |       \
+    (((((PyDateTime_DateTime*)o)->data[7] & _PyDateTime_USECOND_MSB_VALUE_MASK) << 16) |       \
      (((PyDateTime_DateTime*)o)->data[8] << 8)  |       \
       ((PyDateTime_DateTime*)o)->data[9])
+#define PyDateTime_DATE_GET_NANOSECOND(o)               \
+    ((((PyDateTime_Date*)o)->data[10] << 8) | \
+     ((PyDateTime_Date*)o)->data[11])
+
+#define PyDateTime_DATE_PICKLE_GET_VERSION(o)  (((((PyDateTime_DateTime*)o)->data[7]) & _PyDateTime_USECOND_MSB_PICKLEVERSION_MASK) >> 8 )
+#define PyDateTime_DATE_PICKLE_SET_VERSION(o,v)  (((PyDateTime_DateTime*)o)->data[7] |= (v<<8))
 
 /* Apply for time instances. */
 #define PyDateTime_TIME_GET_HOUR(o)        (((PyDateTime_Time*)o)->data[0])
 #define PyDateTime_TIME_GET_MINUTE(o)      (((PyDateTime_Time*)o)->data[1])
 #define PyDateTime_TIME_GET_SECOND(o)      (((PyDateTime_Time*)o)->data[2])
 #define PyDateTime_TIME_GET_MICROSECOND(o)              \
-    ((((PyDateTime_Time*)o)->data[3] << 16) |           \
+    (((((PyDateTime_Time*)o)->data[3] & _PyDateTime_USECOND_MSB_VALUE_MASK) << 16) |           \
      (((PyDateTime_Time*)o)->data[4] << 8)  |           \
       ((PyDateTime_Time*)o)->data[5])
+#define PyDateTime_TIME_GET_NANOSECOND(o)               \
+    ((((PyDateTime_Date*)o)->data[6] << 8) | \
+     ((PyDateTime_Date*)o)->data[7])
+
+#define PyDateTime_TIME_PICKLE_GET_VERSION(o)  (((((PyDateTime_Time*)o)->data[3]) & _PyDateTime_USECOND_MSB_PICKLEVERSION_MASK) >> 8 )
+#define PyDateTime_TIME_PICKLE_SET_VERSION(o,v)  (((PyDateTime_DateTime*)o)->data[3] |= (v<<8))
 
 /* Apply for time delta instances */
 #define PyDateTime_DELTA_GET_DAYS(o)         (((PyDateTime_Delta*)o)->days)
@@ -153,13 +182,14 @@
 
     /* constructors */
     PyObject *(*Date_FromDate)(int, int, int, PyTypeObject*);
-    PyObject *(*DateTime_FromDateAndTime)(int, int, int, int, int, int, int,
+    PyObject *(*DateTime_FromDateAndTime)(int, int, int, int, int, int, int, int,
         PyObject*, PyTypeObject*);
-    PyObject *(*Time_FromTime)(int, int, int, int, PyObject*, PyTypeObject*);
-    PyObject *(*Delta_FromDelta)(int, int, int, int, PyTypeObject*);
+    PyObject *(*Time_FromTime)(int, int, int, int, int, PyObject*, PyTypeObject*);
+    PyObject *(*Delta_FromDelta)(int, int, int, int, int, PyTypeObject*);
 
     /* constructors for the DB API */
     PyObject *(*DateTime_FromTimestamp)(PyObject*, PyObject*, PyObject*);
+    PyObject *(*DateTime_FromTimespec)(PyObject*, PyObject*, PyObject*);
     PyObject *(*Date_FromTimestamp)(PyObject*, PyObject*);
 
 } PyDateTime_CAPI;
@@ -230,6 +260,10 @@
     PyDateTimeAPI->DateTime_FromTimestamp( \
         (PyObject*) (PyDateTimeAPI->DateTimeType), args, NULL)
 
+#define PyDateTime_FromTimespec(args) \
+    PyDateTimeAPI->DateTime_FromTimespec( \
+        (PyObject*) (PyDateTimeAPI->DateTimeType), args, NULL)
+
 #define PyDate_FromTimestamp(args) \
     PyDateTimeAPI->Date_FromTimestamp( \
         (PyObject*) (PyDateTimeAPI->DateType), args)
diff -r 5754f069b123 Lib/datetime.py
--- a/Lib/datetime.py	Sat Nov 22 12:54:57 2014 -0800
+++ b/Lib/datetime.py	Tue Dec 16 09:04:35 2014 -0800
@@ -631,6 +631,7 @@
 
     __new__()
     fromtimestamp()
+    fromtimespec()
     today()
     fromordinal()
 
@@ -683,7 +684,7 @@
         "Construct a date from a POSIX timestamp (like time.time())."
         y, m, d, hh, mm, ss, weekday, jday, dst = _time.localtime(t)
         return cls(y, m, d)
-
+    
     @classmethod
     def today(cls):
         "Construct a date from time.time()."
@@ -1388,6 +1389,12 @@
             result = tz.fromutc(result)
         return result
 
+    
+    @classmethod
+    def fromtimespec(cls, t):
+        "Construct a date from a POSIX timespec."
+        return cls(t.tv_sec + 1e-9 * t.tv_nsec)
+
     @classmethod
     def utcfromtimestamp(cls, t):
         "Construct a UTC datetime from a POSIX timestamp (like time.time())."
diff -r 5754f069b123 Modules/_datetimemodule.c
--- a/Modules/_datetimemodule.c	Sat Nov 22 12:54:57 2014 -0800
+++ b/Modules/_datetimemodule.c	Tue Dec 16 09:04:35 2014 -0800
@@ -50,6 +50,7 @@
 #define DATE_GET_MINUTE         PyDateTime_DATE_GET_MINUTE
 #define DATE_GET_SECOND         PyDateTime_DATE_GET_SECOND
 #define DATE_GET_MICROSECOND    PyDateTime_DATE_GET_MICROSECOND
+#define DATE_GET_NANOSECOND     PyDateTime_DATE_GET_NANOSECOND
 
 /* Date accessors for date and datetime. */
 #define SET_YEAR(o, v)          (((o)->data[0] = ((v) & 0xff00) >> 8), \
@@ -62,31 +63,39 @@
 #define DATE_SET_MINUTE(o, v)   (PyDateTime_DATE_GET_MINUTE(o) = (v))
 #define DATE_SET_SECOND(o, v)   (PyDateTime_DATE_GET_SECOND(o) = (v))
 #define DATE_SET_MICROSECOND(o, v)      \
-    (((o)->data[7] = ((v) & 0xff0000) >> 16), \
+    (((o)->data[7] = (((v) & 0xff0000) >> 16) & _PyDateTime_PICKLE_CURRENT_VERSION), \
      ((o)->data[8] = ((v) & 0x00ff00) >> 8), \
      ((o)->data[9] = ((v) & 0x0000ff)))
-
+#define DATE_SET_NANOSECOND(o, v)      \
+    (((o)->data[10] = ((v) & 0xff00) >> 8), \
+     ((o)->data[11] = ((v) & 0x00ff)))
 /* Time accessors for time. */
 #define TIME_GET_HOUR           PyDateTime_TIME_GET_HOUR
 #define TIME_GET_MINUTE         PyDateTime_TIME_GET_MINUTE
 #define TIME_GET_SECOND         PyDateTime_TIME_GET_SECOND
 #define TIME_GET_MICROSECOND    PyDateTime_TIME_GET_MICROSECOND
+#define TIME_GET_NANOSECOND     PyDateTime_TIME_GET_NANOSECOND
 #define TIME_SET_HOUR(o, v)     (PyDateTime_TIME_GET_HOUR(o) = (v))
 #define TIME_SET_MINUTE(o, v)   (PyDateTime_TIME_GET_MINUTE(o) = (v))
 #define TIME_SET_SECOND(o, v)   (PyDateTime_TIME_GET_SECOND(o) = (v))
 #define TIME_SET_MICROSECOND(o, v)      \
-    (((o)->data[3] = ((v) & 0xff0000) >> 16), \
+    (((o)->data[3] = (((v) & 0xff0000) >> 16) & _PyDateTime_PICKLE_CURRENT_VERSION), \
      ((o)->data[4] = ((v) & 0x00ff00) >> 8), \
      ((o)->data[5] = ((v) & 0x0000ff)))
+#define TIME_SET_NANOSECOND(o, v)      \
+    (((o)->data[6] = ((v) & 0xff00) >> 8), \
+     ((o)->data[7] = ((v) & 0x00ff)))
 
 /* Delta accessors for timedelta. */
 #define GET_TD_DAYS(o)          (((PyDateTime_Delta *)(o))->days)
 #define GET_TD_SECONDS(o)       (((PyDateTime_Delta *)(o))->seconds)
 #define GET_TD_MICROSECONDS(o)  (((PyDateTime_Delta *)(o))->microseconds)
+#define GET_TD_NANOSECONDS(o)   (((PyDateTime_Delta *)(o))->nanoseconds)
 
 #define SET_TD_DAYS(o, v)       ((o)->days = (v))
 #define SET_TD_SECONDS(o, v)    ((o)->seconds = (v))
 #define SET_TD_MICROSECONDS(o, v) ((o)->microseconds = (v))
+#define SET_TD_NANOSECONDS(o, v)  ((o)->nanoseconds = (v))
 
 /* p is a pointer to a time or a datetime object; HASTZINFO(p) returns
  * p->hastzinfo.
@@ -103,12 +112,14 @@
 #define MONTH_IS_SANE(M) ((unsigned int)(M) - 1 < 12)
 
 /* Forward declarations. */
+static int initialized;
 static PyTypeObject PyDateTime_DateType;
 static PyTypeObject PyDateTime_DateTimeType;
 static PyTypeObject PyDateTime_DeltaType;
 static PyTypeObject PyDateTime_TimeType;
 static PyTypeObject PyDateTime_TZInfoType;
 static PyTypeObject PyDateTime_TimeZoneType;
+static PyTypeObject PyDateTime_StructTimespecType;
 
 _Py_IDENTIFIER(as_integer_ratio);
 _Py_IDENTIFIER(fromutc);
@@ -669,7 +680,7 @@
 /* Create a datetime instance with no range checking. */
 static PyObject *
 new_datetime_ex(int year, int month, int day, int hour, int minute,
-             int second, int usecond, PyObject *tzinfo, PyTypeObject *type)
+             int second, int usecond, int nsecond, PyObject *tzinfo, PyTypeObject *type)
 {
     PyDateTime_DateTime *self;
     char aware = tzinfo != Py_None;
@@ -682,6 +693,7 @@
         DATE_SET_MINUTE(self, minute);
         DATE_SET_SECOND(self, second);
         DATE_SET_MICROSECOND(self, usecond);
+        DATE_SET_NANOSECOND(self, nsecond);
         if (aware) {
             Py_INCREF(tzinfo);
             self->tzinfo = tzinfo;
@@ -690,14 +702,14 @@
     return (PyObject *)self;
 }
 
-#define new_datetime(y, m, d, hh, mm, ss, us, tzinfo)           \
-    new_datetime_ex(y, m, d, hh, mm, ss, us, tzinfo,            \
+#define new_datetime(y, m, d, hh, mm, ss, us, ns, tzinfo)           \
+    new_datetime_ex(y, m, d, hh, mm, ss, us, ns, tzinfo,            \
                     &PyDateTime_DateTimeType)
 
 /* Create a time instance with no range checking. */
 static PyObject *
 new_time_ex(int hour, int minute, int second, int usecond,
-            PyObject *tzinfo, PyTypeObject *type)
+            int nsecond, PyObject *tzinfo, PyTypeObject *type)
 {
     PyDateTime_Time *self;
     char aware = tzinfo != Py_None;
@@ -710,6 +722,7 @@
         TIME_SET_MINUTE(self, minute);
         TIME_SET_SECOND(self, second);
         TIME_SET_MICROSECOND(self, usecond);
+        TIME_SET_NANOSECOND(self, nsecond);
         if (aware) {
             Py_INCREF(tzinfo);
             self->tzinfo = tzinfo;
@@ -718,8 +731,8 @@
     return (PyObject *)self;
 }
 
-#define new_time(hh, mm, ss, us, tzinfo)                \
-    new_time_ex(hh, mm, ss, us, tzinfo, &PyDateTime_TimeType)
+#define new_time(hh, mm, ss, us, ns, tzinfo)                \
+    new_time_ex(hh, mm, ss, us, ns, tzinfo, &PyDateTime_TimeType)
 
 /* Create a timedelta instance.  Normalize the members iff normalize is
  * true.  Passing false is a speed optimization, if you know for sure
@@ -728,8 +741,8 @@
  * of range).
  */
 static PyObject *
-new_delta_ex(int days, int seconds, int microseconds, int normalize,
-             PyTypeObject *type)
+new_delta_ex(int days, int seconds, int microseconds, int nanoseconds,
+             int normalize, PyTypeObject *type)
 {
     PyDateTime_Delta *self;
 
@@ -747,12 +760,13 @@
         SET_TD_DAYS(self, days);
         SET_TD_SECONDS(self, seconds);
         SET_TD_MICROSECONDS(self, microseconds);
+        SET_TD_NANOSECONDS(self, nanoseconds);
     }
     return (PyObject *) self;
 }
 
-#define new_delta(d, s, us, normalize)  \
-    new_delta_ex(d, s, us, normalize, &PyDateTime_DeltaType)
+#define new_delta(d, s, us, ns, normalize)  \
+    new_delta_ex(d, s, us, ns, normalize, &PyDateTime_DeltaType)
 
 
 typedef struct
@@ -1131,6 +1145,20 @@
     return PyBytes_FromStringAndSize(freplacement, strlen(freplacement));
 }
 
+static PyObject *
+make_Nreplacement(PyObject *object)
+{
+    char Nreplacement[64];
+    if (PyTime_Check(object))
+        sprintf(Nreplacement, "%09d", (int) (TIME_GET_MICROSECOND(object) * 1e3 + TIME_GET_NANOSECOND(object)));
+    else if (PyDateTime_Check(object))
+        sprintf(Nreplacement, "%09d", (int) (DATE_GET_MICROSECOND(object) * 1e3 + DATE_GET_NANOSECOND(object)));
+    else
+        sprintf(Nreplacement, "%09d", 0);
+
+    return PyBytes_FromStringAndSize(Nreplacement, strlen(Nreplacement));
+}
+
 /* I sure don't want to reproduce the strftime code from the time module,
  * so this imports the module and calls it.  All the hair is due to
  * giving special meanings to the %z, %Z and %f format codes via a
@@ -1147,6 +1175,7 @@
     PyObject *zreplacement = NULL;      /* py string, replacement for %z */
     PyObject *Zreplacement = NULL;      /* py string, replacement for %Z */
     PyObject *freplacement = NULL;      /* py string, replacement for %f */
+    PyObject *Nreplacement = NULL;      /* py string, replacement for %N */
 
     const char *pin;            /* pointer to next char in input format */
     Py_ssize_t flen;            /* length of input format */
@@ -1249,6 +1278,18 @@
             ptoappend = PyBytes_AS_STRING(freplacement);
             ntoappend = PyBytes_GET_SIZE(freplacement);
         }
+        else if (ch == 'N') {
+            /* format nanoseconds */
+            if (Nreplacement == NULL) {
+                Nreplacement = make_Nreplacement(object);
+                if (Nreplacement == NULL)
+                    goto Done;
+            }
+            assert(Nreplacement != NULL);
+            assert(PyBytes_Check(Nreplacement));
+            ptoappend = PyBytes_AS_STRING(Nreplacement);
+            ntoappend = PyBytes_GET_SIZE(Nreplacement);
+        }
         else {
             /* percent followed by neither z nor Z */
             ptoappend = pin - 2;
@@ -1295,6 +1336,7 @@
         Py_DECREF(time);
     }
  Done:
+    Py_XDECREF(Nreplacement);
     Py_XDECREF(freplacement);
     Py_XDECREF(zreplacement);
     Py_XDECREF(Zreplacement);
@@ -1537,7 +1579,7 @@
                         "large to fit in a C int");
         goto Done;
     }
-    result = new_delta_ex(d, s, us, 0, type);
+    result = new_delta_ex(d, s, us, 0 /* XXX ns */, 0, type);
 
 Done:
     Py_XDECREF(tuple);
@@ -1730,7 +1772,7 @@
         int seconds = GET_TD_SECONDS(left) + GET_TD_SECONDS(right);
         int microseconds = GET_TD_MICROSECONDS(left) +
                            GET_TD_MICROSECONDS(right);
-        result = new_delta(days, seconds, microseconds, 1);
+        result = new_delta(days, seconds, microseconds, 0 /* ns XXX */,1);
     }
 
     if (result == Py_NotImplemented)
@@ -1743,7 +1785,7 @@
 {
     return new_delta(-GET_TD_DAYS(self),
                      -GET_TD_SECONDS(self),
-                     -GET_TD_MICROSECONDS(self),
+                     -GET_TD_MICROSECONDS(self), 0 /* ns XXX */,
                      1);
 }
 
@@ -1755,7 +1797,7 @@
      */
     return new_delta(GET_TD_DAYS(self),
                      GET_TD_SECONDS(self),
-                     GET_TD_MICROSECONDS(self),
+                     GET_TD_MICROSECONDS(self), 0 /* ns XXX */,
                      0);
 }
 
@@ -1789,7 +1831,7 @@
         int seconds = GET_TD_SECONDS(left) - GET_TD_SECONDS(right);
         int microseconds = GET_TD_MICROSECONDS(left) -
                            GET_TD_MICROSECONDS(right);
-        result = new_delta(days, seconds, microseconds, 1);
+        result = new_delta(days, seconds, microseconds, 0 /* ns XXX */, 1);
     }
 
     if (result == Py_NotImplemented)
@@ -2608,7 +2650,7 @@
             int right_ord = ymd_to_ord(GET_YEAR(right),
                                        GET_MONTH(right),
                                        GET_DAY(right));
-            return new_delta(left_ord - right_ord, 0, 0, 0);
+            return new_delta(left_ord - right_ord, 0, 0, 0, 0);
         }
         if (PyDelta_Check(right)) {
             /* date - delta */
@@ -3420,6 +3462,21 @@
     timezone_new,                     /* tp_new */
 };
 
+static PyStructSequence_Field struct_timespec_type_fields[] = {
+    {"tv_sec", "seconds"},
+    {"tv_nsec", "nanoseconds"},
+    {0}
+};
+
+static PyStructSequence_Desc struct_timespec_type_desc = {
+    "datetime.struct_timespec",
+    "POSIX.1b structure for a time value. This is like a `struct timeval' but\n"
+    "has nanoseconds instead of microseconds.",
+    struct_timespec_type_fields,
+    2,
+};
+
+
 /*
  * PyDateTime_Time implementation.
  */
@@ -3453,6 +3510,12 @@
 }
 
 static PyObject *
+time_nanosecond(PyDateTime_Time *self, void *unused)
+{
+    return PyLong_FromLong(TIME_GET_NANOSECOND(self));
+}
+
+static PyObject *
 time_tzinfo(PyDateTime_Time *self, void *unused)
 {
     PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None;
@@ -3465,7 +3528,8 @@
     {"minute",      (getter)time_minute},
     {"second",      (getter)py_time_second},
     {"microsecond", (getter)time_microsecond},
-    {"tzinfo",          (getter)time_tzinfo},
+    {"nanosecond",  (getter)time_nanosecond},
+    {"tzinfo",      (getter)time_tzinfo},
     {NULL}
 };
 
@@ -3491,7 +3555,7 @@
     if (PyTuple_GET_SIZE(args) >= 1 &&
         PyTuple_GET_SIZE(args) <= 2 &&
         PyBytes_Check(state = PyTuple_GET_ITEM(args, 0)) &&
-        PyBytes_GET_SIZE(state) == _PyDateTime_TIME_DATASIZE &&
+        ((PyBytes_GET_SIZE(state) == _PyDateTime_TIME_DATASIZE) || (PyBytes_GET_SIZE(state) == _PyDateTime_TIME_DATASIZE_V0)) &&
         ((unsigned char) (PyBytes_AS_STRING(state)[0])) < 24)
     {
         PyDateTime_Time *me;
@@ -3509,8 +3573,10 @@
         me = (PyDateTime_Time *) (type->tp_alloc(type, aware));
         if (me != NULL) {
             char *pdata = PyBytes_AS_STRING(state);
-
-            memcpy(me->data, pdata, _PyDateTime_TIME_DATASIZE);
+            memset(me->data, 0, _PyDateTime_TIME_DATASIZE);
+            memcpy(me->data, pdata, PyBytes_GET_SIZE(state) /* _PyDateTime_TIME_DATASIZE */ );
+            PyDateTime_TIME_PICKLE_SET_VERSION(me, _PyDateTime_PICKLE_CURRENT_VERSION);
+            
             me->hashcode = -1;
             me->hastzinfo = aware;
             if (aware) {
@@ -3528,7 +3594,7 @@
             return NULL;
         if (check_tzinfo_subclass(tzinfo) < 0)
             return NULL;
-        self = new_time_ex(hour, minute, second, usecond, tzinfo,
+        self = new_time_ex(hour, minute, second, usecond, 0 /* ns XXX */, tzinfo,
                            type);
     }
     return self;
@@ -3579,9 +3645,13 @@
     int m = TIME_GET_MINUTE(self);
     int s = TIME_GET_SECOND(self);
     int us = TIME_GET_MICROSECOND(self);
+    int ns = TIME_GET_NANOSECOND(self);
     PyObject *result = NULL;
 
-    if (us)
+    if (ns)
+        result = PyUnicode_FromFormat("%s(%d, %d, %d, %d, %d)",
+                                      type_name, h, m, s, us, ns);
+    else if (us)
         result = PyUnicode_FromFormat("%s(%d, %d, %d, %d)",
                                       type_name, h, m, s, us);
     else if (s)
@@ -3606,8 +3676,16 @@
     char buf[100];
     PyObject *result;
     int us = TIME_GET_MICROSECOND(self);
-
-    if (us)
+    int ns = TIME_GET_NANOSECOND(self);
+    
+    if (ns)
+        result = PyUnicode_FromFormat("%02d:%02d:%02d.%09d",
+                                      TIME_GET_HOUR(self),
+                                      TIME_GET_MINUTE(self),
+                                      TIME_GET_SECOND(self),
+                                      ns + 1e3 * us);
+
+    else if (us)
         result = PyUnicode_FromFormat("%02d:%02d:%02d.%06d",
                                       TIME_GET_HOUR(self),
                                       TIME_GET_MINUTE(self),
@@ -3717,8 +3795,8 @@
                    GET_TD_SECONDS(offset2);
         diff = offsecs1 - offsecs2;
         if (diff == 0)
-            diff = TIME_GET_MICROSECOND(self) -
-                   TIME_GET_MICROSECOND(other);
+            diff = TIME_GET_MICROSECOND(self) * 1e3 + TIME_GET_NANOSECOND(self) -
+                   TIME_GET_MICROSECOND(other) * 1e3 - TIME_GET_NANOSECOND(other);
         result = diff_to_bool(diff, op);
     }
     else if (op == Py_EQ) {
@@ -3757,13 +3835,14 @@
                 (unsigned char *)self->data, _PyDateTime_TIME_DATASIZE);
         else {
             PyObject *temp1, *temp2;
-            int seconds, microseconds;
+            int seconds, microseconds, nanoseconds;
             assert(HASTZINFO(self));
             seconds = TIME_GET_HOUR(self) * 3600 +
                       TIME_GET_MINUTE(self) * 60 +
                       TIME_GET_SECOND(self);
             microseconds = TIME_GET_MICROSECOND(self);
-            temp1 = new_delta(0, seconds, microseconds, 1);
+            nanoseconds = TIME_GET_NANOSECOND(self);
+            temp1 = new_delta(0, seconds, microseconds, nanoseconds, 1);
             if (temp1 == NULL) {
                 Py_DECREF(offset);
                 return -1;
@@ -3791,13 +3870,14 @@
     int mm = TIME_GET_MINUTE(self);
     int ss = TIME_GET_SECOND(self);
     int us = TIME_GET_MICROSECOND(self);
+    int ns = TIME_GET_NANOSECOND(self);
     PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None;
 
-    if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiO:replace",
+    if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiO:replace",
                                       time_kws,
-                                      &hh, &mm, &ss, &us, &tzinfo))
+                                      &hh, &mm, &ss, &us, &ns, &tzinfo))
         return NULL;
-    tuple = Py_BuildValue("iiiiO", hh, mm, ss, us, tzinfo);
+    tuple = Py_BuildValue("iiiiiO", hh, mm, ss, us, ns, tzinfo);
     if (tuple == NULL)
         return NULL;
     clone = time_new(Py_TYPE(self), tuple, NULL);
@@ -3947,6 +4027,12 @@
 }
 
 static PyObject *
+datetime_nanosecond(PyDateTime_DateTime *self, void *unused)
+{
+    return PyLong_FromLong(DATE_GET_NANOSECOND(self));
+}
+
+static PyObject *
 datetime_tzinfo(PyDateTime_DateTime *self, void *unused)
 {
     PyObject *result = HASTZINFO(self) ? self->tzinfo : Py_None;
@@ -3959,7 +4045,8 @@
     {"minute",      (getter)datetime_minute},
     {"second",      (getter)datetime_second},
     {"microsecond", (getter)datetime_microsecond},
-    {"tzinfo",          (getter)datetime_tzinfo},
+    {"nanosecond",  (getter)datetime_nanosecond},
+    {"tzinfo",      (getter)datetime_tzinfo},
     {NULL}
 };
 
@@ -3990,7 +4077,7 @@
     if (PyTuple_GET_SIZE(args) >= 1 &&
         PyTuple_GET_SIZE(args) <= 2 &&
         PyBytes_Check(state = PyTuple_GET_ITEM(args, 0)) &&
-        PyBytes_GET_SIZE(state) == _PyDateTime_DATETIME_DATASIZE &&
+        ((PyBytes_GET_SIZE(state) == _PyDateTime_DATETIME_DATASIZE) || (PyBytes_GET_SIZE(state) == _PyDateTime_DATETIME_DATASIZE_V0)) &&
         MONTH_IS_SANE(PyBytes_AS_STRING(state)[2]))
     {
         PyDateTime_DateTime *me;
@@ -4009,7 +4096,11 @@
         if (me != NULL) {
             char *pdata = PyBytes_AS_STRING(state);
 
-            memcpy(me->data, pdata, _PyDateTime_DATETIME_DATASIZE);
+            memset(me->data, 0, _PyDateTime_DATETIME_DATASIZE);
+            memcpy(me->data, pdata, PyBytes_GET_SIZE(state) /* _PyDateTime_DATETIME_DATASIZE */);
+
+            PyDateTime_DATE_PICKLE_SET_VERSION(me, _PyDateTime_PICKLE_CURRENT_VERSION);
+
             me->hashcode = -1;
             me->hastzinfo = aware;
             if (aware) {
@@ -4030,7 +4121,7 @@
         if (check_tzinfo_subclass(tzinfo) < 0)
             return NULL;
         self = new_datetime_ex(year, month, day,
-                                hour, minute, second, usecond,
+                                hour, minute, second, usecond, 0 /* ns XXX */,
                                 tzinfo, type);
     }
     return self;
@@ -4040,11 +4131,11 @@
 typedef struct tm *(*TM_FUNC)(const time_t *timer);
 
 /* Internal helper.
- * Build datetime from a time_t and a distinct count of microseconds.
+ * Build datetime from a time_t and a distinct count of nanoseconds.
  * Pass localtime or gmtime for f, to control the interpretation of timet.
  */
 static PyObject *
-datetime_from_timet_and_us(PyObject *cls, TM_FUNC f, time_t timet, int us,
+datetime_from_timet_and_ns(PyObject *cls, TM_FUNC f, time_t timet, int ns,
                            PyObject *tzinfo)
 {
     struct tm *tm;
@@ -4073,7 +4164,7 @@
                                  tm->tm_hour,
                                  tm->tm_min,
                                  tm->tm_sec,
-                                 us,
+                                 (int) (ns / 1e3), // XXX
                                  tzinfo);
 }
 
@@ -4081,7 +4172,7 @@
  * Build datetime from a Python timestamp.  Pass localtime or gmtime for f,
  * to control the interpretation of the timestamp.  Since a double doesn't
  * have enough bits to cover a datetime's full range of precision, it's
- * better to call datetime_from_timet_and_us provided you have a way
+ * better to call datetime_from_timet_and_ns provided you have a way
  * to get that much precision (e.g., C time() isn't good enough).
  */
 static PyObject *
@@ -4093,7 +4184,31 @@
 
     if (_PyTime_ObjectToTimeval(timestamp, &timet, &us, _PyTime_ROUND_DOWN) == -1)
         return NULL;
-    return datetime_from_timet_and_us(cls, f, timet, (int)us, tzinfo);
+    return datetime_from_timet_and_ns(cls, f, timet, (int) (us * 1e3), tzinfo);
+}
+
+/* Internal helper.
+ * Build datetime from a Python struct timespec.
+ */
+static PyObject *
+datetime_from_timespec(PyObject *cls, TM_FUNC f, PyObject *args,
+                        PyObject *tzinfo)
+{
+    struct timespec ts;
+
+    if (!PyTuple_Check(args)) {
+        PyErr_SetString(PyExc_TypeError,
+                        "Tuple or struct_timespec argument required");
+        return NULL;
+    }
+
+    if (!PyArg_ParseTuple(args, "ii",
+                          &ts.tv_sec, &ts.tv_nsec))
+        return NULL;
+
+    return datetime_from_timet_and_ns(cls, f, ts.tv_sec, ts.tv_nsec,
+                                      tzinfo);
+
 }
 
 /* Internal helper.
@@ -4105,7 +4220,7 @@
 {
     _PyTime_timeval t;
     _PyTime_gettimeofday(&t);
-    return datetime_from_timet_and_us(cls, f, t.tv_sec, (int)t.tv_usec,
+    return datetime_from_timet_and_ns(cls, f, t.tv_sec, (int) (t.tv_usec * 1e3),
                                       tzinfo);
 }
 
@@ -4219,6 +4334,24 @@
     return self;
 }
 
+/* Return new local datetime from struct timespec. */
+static PyObject *
+datetime_fromtimespec(PyObject *cls, PyObject *args, PyObject *kw)
+{
+    PyObject *self;
+    PyObject *timespec;
+    static char *keywords[] = {"timespec", NULL};
+
+    if (! PyArg_ParseTupleAndKeywords(args, kw, "O:fromtimespec",
+                                      keywords, &timespec))
+        return NULL;
+
+    self = datetime_from_timespec(cls, gmtime,
+                                   timespec, Py_None);
+    return self;
+}
+
+
 /* Return new UTC datetime from timestamp (Python timestamp -- a double). */
 static PyObject *
 datetime_utcfromtimestamp(PyObject *cls, PyObject *args)
@@ -4268,7 +4401,7 @@
 
         if (HASTZINFO(time))
             tzinfo = ((PyDateTime_Time *)time)->tzinfo;
-        result = PyObject_CallFunction(cls, "iiiiiiiO",
+        result = PyObject_CallFunction(cls, "iiiiiiiiO",
                                         GET_YEAR(date),
                                         GET_MONTH(date),
                                         GET_DAY(date),
@@ -4276,6 +4409,7 @@
                                         TIME_GET_MINUTE(time),
                                         TIME_GET_SECOND(time),
                                         TIME_GET_MICROSECOND(time),
+                                        TIME_GET_NANOSECOND(time),
                                         tzinfo);
     }
     return result;
@@ -4343,7 +4477,7 @@
         return NULL;
     else
         return new_datetime(year, month, day,
-                            hour, minute, second, microsecond,
+                            hour, minute, second, microsecond, 0 /* ns XXX */,
                             HASTZINFO(date) ? date->tzinfo : Py_None);
 }
 
@@ -4432,7 +4566,7 @@
                        DATE_GET_SECOND(right));
             delta_us = DATE_GET_MICROSECOND(left) -
                        DATE_GET_MICROSECOND(right);
-            result = new_delta(delta_d, delta_s, delta_us, 1);
+            result = new_delta(delta_d, delta_s, delta_us, 0 /* ns XXX */, 1);
             if (result == NULL)
                 return NULL;
 
@@ -4465,7 +4599,17 @@
     const char *type_name = Py_TYPE(self)->tp_name;
     PyObject *baserepr;
 
-    if (DATE_GET_MICROSECOND(self)) {
+    if (DATE_GET_NANOSECOND(self)) {
+        baserepr = PyUnicode_FromFormat(
+                      "%s(%d, %d, %d, %d, %d, %d, %d, %d)",
+                      type_name,
+                      GET_YEAR(self), GET_MONTH(self), GET_DAY(self),
+                      DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
+                      DATE_GET_SECOND(self),
+                      DATE_GET_MICROSECOND(self),
+                      DATE_GET_NANOSECOND(self));
+    }
+    else if (DATE_GET_MICROSECOND(self)) {
         baserepr = PyUnicode_FromFormat(
                       "%s(%d, %d, %d, %d, %d, %d, %d)",
                       type_name,
@@ -4508,10 +4652,17 @@
     char buffer[100];
     PyObject *result;
     int us = DATE_GET_MICROSECOND(self);
+    int ns = DATE_GET_NANOSECOND(self);
 
     if (!PyArg_ParseTupleAndKeywords(args, kw, "|C:isoformat", keywords, &sep))
         return NULL;
-    if (us)
+    if (ns)
+        result = PyUnicode_FromFormat("%04d-%02d-%02d%c%02d:%02d:%02d.%09d",
+                                      GET_YEAR(self), GET_MONTH(self),
+                                      GET_DAY(self), (int)sep,
+                                      DATE_GET_HOUR(self), DATE_GET_MINUTE(self),
+                                      DATE_GET_SECOND(self), us * 1e3 + ns);
+    else if (us)
         result = PyUnicode_FromFormat("%04d-%02d-%02d%c%02d:%02d:%02d.%06d",
                                       GET_YEAR(self), GET_MONTH(self),
                                       GET_DAY(self), (int)sep,
@@ -4658,7 +4809,7 @@
                       DATE_GET_MINUTE(self) * 60 +
                       DATE_GET_SECOND(self);
             temp1 = new_delta(days, seconds,
-                              DATE_GET_MICROSECOND(self),
+                              DATE_GET_MICROSECOND(self), 0 /* ns XXX */,
                               1);
             if (temp1 == NULL) {
                 Py_DECREF(offset);
@@ -4690,14 +4841,15 @@
     int mm = DATE_GET_MINUTE(self);
     int ss = DATE_GET_SECOND(self);
     int us = DATE_GET_MICROSECOND(self);
+    int ns = DATE_GET_NANOSECOND(self);
     PyObject *tzinfo = HASTZINFO(self) ? self->tzinfo : Py_None;
 
-    if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiiiO:replace",
+    if (! PyArg_ParseTupleAndKeywords(args, kw, "|iiiiiiiiO:replace",
                                       datetime_kws,
                                       &y, &m, &d, &hh, &mm, &ss, &us,
-                                      &tzinfo))
+                                      &ns, &tzinfo))
         return NULL;
-    tuple = Py_BuildValue("iiiiiiiO", y, m, d, hh, mm, ss, us, tzinfo);
+    tuple = Py_BuildValue("iiiiiiiiO", y, m, d, hh, mm, ss, us, ns, tzinfo);
     if (tuple == NULL)
         return NULL;
     clone = datetime_new(Py_TYPE(self), tuple, NULL);
@@ -4720,7 +4872,7 @@
     delta = datetime_subtract((PyObject *)utc_time, PyDateTime_Epoch);
     if (delta == NULL)
         return NULL;
-    one_second = new_delta(0, 1, 0, 0);
+    one_second = new_delta(0, 1, 0, 0 /* ns XXX */, 0);
     if (one_second == NULL)
         goto error;
     seconds = divide_timedelta_timedelta((PyDateTime_Delta *)delta,
@@ -4736,14 +4888,14 @@
     timep = localtime(&timestamp);
 #ifdef HAVE_STRUCT_TM_TM_ZONE
     zone = timep->tm_zone;
-    delta = new_delta(0, timep->tm_gmtoff, 0, 1);
+    delta = new_delta(0, timep->tm_gmtoff, 0, 0 /* ns XXX */, 1);
 #else /* HAVE_STRUCT_TM_TM_ZONE */
     {
         PyObject *local_time;
         local_time = new_datetime(timep->tm_year + 1900, timep->tm_mon + 1,
                                   timep->tm_mday, timep->tm_hour, timep->tm_min,
                                   timep->tm_sec, DATE_GET_MICROSECOND(utc_time),
-                                  utc_time->tzinfo);
+                                  DATE_GET_NANOSECOND(utc_time), utc_time->tzinfo);
         if (local_time == NULL)
             goto error;
         delta = datetime_subtract(local_time, (PyObject*)utc_time);
@@ -4899,7 +5051,7 @@
                             "timestamp out of range");
             return NULL;
         }
-        result = PyFloat_FromDouble(timestamp + DATE_GET_MICROSECOND(self) / 1e6);
+        result = PyFloat_FromDouble(timestamp + DATE_GET_MICROSECOND(self) / 1e6 + DATE_GET_NANOSECOND(self) / 1e9);
     }
     return result;
 }
@@ -4919,6 +5071,7 @@
                     DATE_GET_MINUTE(self),
                     DATE_GET_SECOND(self),
                     DATE_GET_MICROSECOND(self),
+                    DATE_GET_NANOSECOND(self),
                     Py_None);
 }
 
@@ -4929,6 +5082,7 @@
                     DATE_GET_MINUTE(self),
                     DATE_GET_SECOND(self),
                     DATE_GET_MICROSECOND(self),
+                    DATE_GET_NANOSECOND(self),
                     GET_DT_TZINFO(self));
 }
 
@@ -5018,6 +5172,10 @@
      METH_VARARGS | METH_KEYWORDS | METH_CLASS,
      PyDoc_STR("timestamp[, tz] -> tz's local time from POSIX timestamp.")},
 
+    {"fromtimespec", (PyCFunction)datetime_fromtimespec,
+     METH_VARARGS | METH_KEYWORDS | METH_CLASS,
+     PyDoc_STR("timespec[, tz] -> tz's local time from POSIX timestamp.")},
+
     {"utcfromtimestamp", (PyCFunction)datetime_utcfromtimestamp,
      METH_VARARGS | METH_CLASS,
      PyDoc_STR("timestamp -> UTC datetime from a POSIX timestamp "
@@ -5165,6 +5323,7 @@
     new_time_ex,
     new_delta_ex,
     datetime_fromtimestamp,
+    datetime_fromtimespec,
     date_fromtimestamp
 };
 
@@ -5210,17 +5369,17 @@
     /* timedelta values */
     d = PyDateTime_DeltaType.tp_dict;
 
-    x = new_delta(0, 0, 1, 0);
+    x = new_delta(0, 0, 1, 0 /* ns XXX */, 0);
     if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
         return NULL;
     Py_DECREF(x);
 
-    x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0);
+    x = new_delta(-MAX_DELTA_DAYS, 0, 0, 0 /* ns XXX */, 0);
     if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
         return NULL;
     Py_DECREF(x);
 
-    x = new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0);
+    x = new_delta(MAX_DELTA_DAYS, 24*3600-1, 1000000-1, 0 /* ns XXX */, 0);
     if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
         return NULL;
     Py_DECREF(x);
@@ -5238,7 +5397,7 @@
         return NULL;
     Py_DECREF(x);
 
-    x = new_delta(1, 0, 0, 0);
+    x = new_delta(1, 0, 0, 0 /* ns XXX */, 0);
     if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
         return NULL;
     Py_DECREF(x);
@@ -5246,17 +5405,17 @@
     /* time values */
     d = PyDateTime_TimeType.tp_dict;
 
-    x = new_time(0, 0, 0, 0, Py_None);
+    x = new_time(0, 0, 0, 0, 0 /* ns XXX */, Py_None);
     if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
         return NULL;
     Py_DECREF(x);
 
-    x = new_time(23, 59, 59, 999999, Py_None);
+    x = new_time(23, 59, 59, 999999, 0 /* ns XXX */, Py_None);
     if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
         return NULL;
     Py_DECREF(x);
 
-    x = new_delta(0, 0, 1, 0);
+    x = new_delta(0, 0, 1, 0 /* ns XXX */, 0);
     if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
         return NULL;
     Py_DECREF(x);
@@ -5264,17 +5423,17 @@
     /* datetime values */
     d = PyDateTime_DateTimeType.tp_dict;
 
-    x = new_datetime(1, 1, 1, 0, 0, 0, 0, Py_None);
+    x = new_datetime(1, 1, 1, 0, 0, 0, 0, 0 /* ns XXX */, Py_None);
     if (x == NULL || PyDict_SetItemString(d, "min", x) < 0)
         return NULL;
     Py_DECREF(x);
 
-    x = new_datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, Py_None);
+    x = new_datetime(MAXYEAR, 12, 31, 23, 59, 59, 999999, 0 /* ns XXX */, Py_None);
     if (x == NULL || PyDict_SetItemString(d, "max", x) < 0)
         return NULL;
     Py_DECREF(x);
 
-    x = new_delta(0, 0, 1, 0);
+    x = new_delta(0, 0, 1, 0 /* ns XXX */, 0);
     if (x == NULL || PyDict_SetItemString(d, "resolution", x) < 0)
         return NULL;
     Py_DECREF(x);
@@ -5282,7 +5441,7 @@
     /* timezone values */
     d = PyDateTime_TimeZoneType.tp_dict;
 
-    delta = new_delta(0, 0, 0, 0);
+    delta = new_delta(0, 0, 0, 0 /* ns XXX */, 0);
     if (delta == NULL)
         return NULL;
     x = create_timezone(delta, NULL);
@@ -5291,7 +5450,7 @@
         return NULL;
     PyDateTime_TimeZone_UTC = x;
 
-    delta = new_delta(-1, 60, 0, 1); /* -23:59 */
+    delta = new_delta(-1, 60, 0, 0 /* ns XXX */, 1); /* -23:59 */
     if (delta == NULL)
         return NULL;
     x = create_timezone(delta, NULL);
@@ -5300,7 +5459,7 @@
         return NULL;
     Py_DECREF(x);
 
-    delta = new_delta(0, (23 * 60 + 59) * 60, 0, 0); /* +23:59 */
+    delta = new_delta(0, (23 * 60 + 59) * 60, 0, 0 /* ns XXX */, 0); /* +23:59 */
     if (delta == NULL)
         return NULL;
     x = create_timezone(delta, NULL);
@@ -5310,7 +5469,7 @@
     Py_DECREF(x);
 
     /* Epoch */
-    PyDateTime_Epoch = new_datetime(1970, 1, 1, 0, 0, 0, 0,
+    PyDateTime_Epoch = new_datetime(1970, 1, 1, 0, 0, 0, 0, 0 /* ns XXX */,
                                     PyDateTime_TimeZone_UTC);
     if (PyDateTime_Epoch == NULL)
       return NULL;
@@ -5338,6 +5497,14 @@
     Py_INCREF(&PyDateTime_TimeZoneType);
     PyModule_AddObject(m, "timezone", (PyObject *) &PyDateTime_TimeZoneType);
 
+    if (!initialized) {
+        if (PyStructSequence_InitType2(&PyDateTime_StructTimespecType,
+                                       &struct_timespec_type_desc) < 0)
+            return NULL;
+    }
+    Py_INCREF(&PyDateTime_StructTimespecType);
+    PyModule_AddObject(m, "struct_timespec", (PyObject *) &PyDateTime_StructTimespecType);
+
     x = PyCapsule_New(&CAPI, PyDateTime_CAPSULE_NAME, NULL);
     if (x == NULL)
         return NULL;
@@ -5378,6 +5545,7 @@
     us_per_week = PyLong_FromDouble(604800000000.0);
     if (us_per_hour == NULL || us_per_day == NULL || us_per_week == NULL)
         return NULL;
+    initialized = 1;
     return m;
 }
 
