commit 4d998c9d6b130ed4e2d54cb96b010fec749a9c59
Author: xtreak <tir.karthi@gmail.com>
Date:   Wed Jun 19 14:54:22 2019 +0000

    Patch time.time_ns to support Python 3.8

diff --git a/CHANGELOG b/CHANGELOG
index efac4d3..14d96be 100644
--- a/CHANGELOG
+++ b/CHANGELOG
@@ -11,6 +11,7 @@ Latest
 * Ignore Selenium
 * Move to pytest
 * Conditionally patch time.clock
+* Patch time.time_ns added in Python 3.7
 
 0.3.11
 ------
@@ -57,4 +58,4 @@ Latest
 
 * Add `tick` argument to allow time to move forward
 * Performance improvements
-* Fix timezone example in README
\ No newline at end of file
+* Fix timezone example in README
diff --git a/freezegun/api.py b/freezegun/api.py
index 5e7d7fa..bc61270 100644
--- a/freezegun/api.py
+++ b/freezegun/api.py
@@ -20,6 +20,7 @@ try:
 except ImportError:
     MayaDT = None
 
+_TIME_NS_PRESENT = hasattr(time, 'time_ns')
 
 real_time = time.time
 real_localtime = time.localtime
@@ -28,6 +29,11 @@ real_strftime = time.strftime
 real_date = datetime.date
 real_datetime = datetime.datetime
 real_date_objects = [real_time, real_localtime, real_gmtime, real_strftime, real_date, real_datetime]
+
+if _TIME_NS_PRESENT:
+    real_time_ns = time.time_ns
+    real_date_objects.append(real_time_ns)
+
 _real_time_object_ids = set(id(obj) for obj in real_date_objects)
 
 # time.clock is deprecated and was removed in Python 3.8
@@ -175,6 +181,12 @@ def fake_time():
     current_time = get_current_time()
     return calendar.timegm(current_time.timetuple()) + current_time.microsecond / 1000000.0
 
+if _TIME_NS_PRESENT:
+    def fake_time_ns():
+        if _should_use_real_time():
+            return real_time_ns()
+        return int(int(fake_time()) * 1e9)
+
 
 def fake_localtime(t=None):
     if t is not None:
@@ -331,7 +343,7 @@ class FakeDatetime(with_metaclass(FakeDatetimeMeta, real_datetime, FakeDate)):
 
     def date(self):
         return date_to_fakedate(self)
-    
+
     @property
     def nanosecond(self):
         try:
@@ -599,6 +611,10 @@ class _freeze_time(object):
             ('real_time', real_time, fake_time),
         ]
 
+        if _TIME_NS_PRESENT:
+            time.time_ns = fake_time_ns
+            to_patch.append(('real_time_ns', real_time_ns, fake_time_ns))
+
         if real_clock is not None:
             # time.clock is deprecated and was removed in Python 3.8
             time.clock = fake_clock
@@ -741,7 +757,7 @@ def freeze_time(time_to_freeze=None, tz_offset=0, ignore=None, tick=False, as_ar
     ignore.append('selenium')
     ignore.append('_pytest.terminal.')
     ignore.append('_pytest.runner.')
-    
+
     return _freeze_time(time_to_freeze, tz_offset, ignore, tick, as_arg, auto_tick_seconds)
 
 
diff --git a/tests/test_datetimes.py b/tests/test_datetimes.py
index cfef4a1..688fdce 100644
--- a/tests/test_datetimes.py
+++ b/tests/test_datetimes.py
@@ -19,6 +19,7 @@ except ImportError:
 
 # time.clock was removed in Python 3.8
 HAS_CLOCK = hasattr(time, 'clock')
+HAS_TIME_NS = hasattr(time, 'time_ns')
 
 class temp_locale(object):
     """Temporarily change the locale."""
@@ -656,3 +657,18 @@ def test_should_use_real_time():
         assert time.gmtime() != expected_frozen_gmt
         if HAS_CLOCK:
             assert time.clock() != expected_clock
+
+
+@pytest.mark.skipif(not HAS_TIME_NS,
+                    reason="time.time_ns is present only on 3.7 and above")
+def test_time_ns():
+    freezer = freeze_time("2012-01-14")
+    local_time = datetime.datetime(2012, 1, 14)
+    utc_time = local_time - datetime.timedelta(seconds=time.timezone)
+    expected_timestamp = time.mktime(utc_time.timetuple())
+
+    freezer.start()
+    assert time.time() == expected_timestamp
+    assert time.time_ns() == expected_timestamp * 1e9
+    freezer.stop()
+    assert time.time() != expected_timestamp
