coveralls: 
[![Coverage Status](https://coveralls.io/builds/26287741/badge)](https://coveralls.io/builds/26287741)

Coverage increased (+0.1%) to 91.793% when pulling **a35fe80ccc783c577b4f084feae1bcfc220d9a1f on eric-weaver:issue-312-unfreeze-time-ns** into **f70b77c0867fe3bb78cb58570ece031d7fdd34e7 on spulec:master**.

coveralls: 
[![Coverage Status](https://coveralls.io/builds/26287741/badge)](https://coveralls.io/builds/26287741)

Coverage increased (+0.1%) to 91.793% when pulling **a35fe80ccc783c577b4f084feae1bcfc220d9a1f on eric-weaver:issue-312-unfreeze-time-ns** into **f70b77c0867fe3bb78cb58570ece031d7fdd34e7 on spulec:master**.

boxed: Does this work when starting freezegun again? 


Also it seems weird that this specific function is handled very differently from the others. There we just pass through if not frozen. 
eric-weaver: @boxed yes this looks to be working when freezing again. Below are examples tested against python 3.7.4. 

The first one is from current [master](https://github.com/spulec/freezegun/tree/f70b77c0867fe3bb78cb58570ece031d7fdd34e7)
```
/src # git rev-parse --verify HEAD
f70b77c0867fe3bb78cb58570ece031d7fdd34e7
/src # git status
On branch master
Your branch is up to date with 'origin/master'.

nothing to commit, working tree clean
/src # python
Python 3.7.4 (default, Jul 13 2019, 14:44:04) 
[GCC 8.3.0] on linux
>>> import time
>>> time.time(); time.time_ns()
1571353599.7948837
1571353599795022000
>>> from freezegun import freeze_time
>>> freezer = freeze_time('1970-01-01')
>>> time.time(); time.time_ns()
1571353634.7175064
1571353634717627500
>>> freezer.start()
<freezegun.api.FrozenDateTimeFactory object at 0x7f399bc4d8d0>
>>> time.time(); time.time_ns()
0.0
0
>>> freezer.stop()
>>> time.time()
1571353657.3422928
>>> time.time_ns()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/src/freezegun/api.py", line 186, in fake_time_ns
    if _should_use_real_time():
  File "/src/freezegun/api.py", line 157, in _should_use_real_time
    if not ignore_lists[-1]:
IndexError: list index out of range
```

And this is after the changes in this pull request
```
/src # git rev-parse --verify HEAD
a35fe80ccc783c577b4f084feae1bcfc220d9a1f
/src # git status
On branch issue-312-unfreeze-time-ns
Your branch is up to date with 'origin/issue-312-unfreeze-time-ns'.

nothing to commit, working tree clean
/src # python
Python 3.7.4 (default, Jul 13 2019, 14:44:04) 
[GCC 8.3.0] on linux
>>> import time
>>> time.time();time.time_ns()
1571354000.6646214
1571354000664727500
>>> from freezegun import freeze_time
>>> freezer = freeze_time('1970-01-01')
>>> time.time();time.time_ns()
1571354021.676702
1571354021676739800
>>> freezer.start()
<freezegun.api.FrozenDateTimeFactory object at 0x7fe225308dd0>
>>> time.time();time.time_ns()
0.0
0
>>> freezer.stop()
>>> time.time();time.time_ns()
1571354042.633977
1571354042634079200
>>> freezer.start()
<freezegun.api.FrozenDateTimeFactory object at 0x7fe22571f350>
>>> time.time();time.time_ns()
0.0
0
>>> freezer.stop()
>>> time.time();time.time_ns()
1571354063.045664
1571354063045720100
>>> freezer = freeze_time('2000-01-01')
>>> freezer.start()
<freezegun.api.FrozenDateTimeFactory object at 0x7fe225318850>
>>> time.time();time.time_ns()
946684800.0
946684800000000000
>>> freezer.stop()
>>> time.time();time.time_ns()
1571354090.9213243
1571354090921366600
```
eric-weaver: Also I agree that the implementation of freezing `time_ns` is different than everything else in this module. One reason I presume is because this function was only introduced in python 3.7. I'd be happy to take a stab at cleaning it up either in this PR or another if there is a better pattern we wish to follow here. [clock](https://github.com/spulec/freezegun/blob/011138dc548bcf77c237a9f4f334b2838aa9d10b/freezegun/api.py#L41) is another function that needs to be implemented special as it's removed in 3.8. I also noticed in #277 there's reference to adding `time.perf_counter` which was only introduced in python 3.3 and it has a sibling `time.perf_counter_ns` introduced in 3.7. I point these out as there is a lot being added/removed from the time module in recent versions. Would be interested in any thoughts on how to standardize compatibility between them in freezegun
boxed: Maybe we should just pull in these fixes for low and clean up later. It's often easier to see the pattern after a few cases. 
boxed: There's conflicts on this PR now btw. 
diff --git a/freezegun/api.py b/freezegun/api.py
index b32e3ed..667c657 100644
--- a/freezegun/api.py
+++ b/freezegun/api.py
@@ -709,6 +709,9 @@ class _freeze_time(object):
             time.strftime = real_strftime
             time.clock = real_clock
 
+            if _TIME_NS_PRESENT:
+                time.time_ns = real_time_ns
+
             if uuid_generate_time_attr:
                 setattr(uuid, uuid_generate_time_attr, real_uuid_generate_time)
             uuid._UuidCreate = real_uuid_create

Freezegun does not unfreeze `time.time_ns()`
Currently when Freezegun stops freezing time `time.time_ns()` is still faked. This leads to the following exception on the next call to `time.time_ns()`

```
/src # git rev-parse --verify HEAD
f70b77c0867fe3bb78cb58570ece031d7fdd34e7
/src # git status
On branch master
Your branch is up to date with 'origin/master'.


/src # python
Python 3.7.4 (default, Jul 13 2019, 14:44:04) 
[GCC 8.3.0] on linux
>>> import time
>>> time.time(); time.time_ns()
1571353599.7948837
1571353599795022000
>>> from freezegun import freeze_time
>>> freezer = freeze_time('1970-01-01')
>>> time.time(); time.time_ns()
1571353634.7175064
1571353634717627500
>>> freezer.start()
<freezegun.api.FrozenDateTimeFactory object at 0x7f399bc4d8d0>
>>> time.time(); time.time_ns()
0.0
0
>>> freezer.stop()
>>> time.time()
1571353657.3422928
>>> time.time_ns()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/src/freezegun/api.py", line 186, in fake_time_ns
    if _should_use_real_time():
  File "/src/freezegun/api.py", line 157, in _should_use_real_time
    if not ignore_lists[-1]:
IndexError: list index out of range
```
diff --git a/tests/test_datetimes.py b/tests/test_datetimes.py
index a431104..a5f0b93 100644
--- a/tests/test_datetimes.py
+++ b/tests/test_datetimes.py
@@ -690,6 +690,7 @@ def test_time_ns():
     assert time.time_ns() == expected_timestamp * 1e9
     freezer.stop()
     assert time.time() != expected_timestamp
+    assert time.time_ns() != expected_timestamp * 1e9
 
 
 @pytest.mark.skip("timezone handling is currently incorrect")

pip install -e .[dev]
parse_log_pytest
requirements.txt
pytest pytest-cov pytest-xdist pytest-mock pytest-asyncio pytest-bdd pytest-benchmark pytest-randomly responses mock hypothesis freezegun trustme requests-mock requests tomlkit
apt-get update apt-get install -y gcc
3.9
requirements.txt
pytest --no-header -rA --tb=line --color=no -p no:cacheprovider -W ignore::DeprecationWarning
atomicwrites==1.4.1
attrs==25.3.0
certifi==2025.1.31
cffi==1.17.1
charset-normalizer==3.4.1
coverage==7.8.0
coveralls==4.0.1
cryptography==44.0.2
dateparser==1.2.1
docopt==0.6.2
exceptiongroup==1.2.2
execnet==2.1.1
-e git+https://github.com/spulec/freezegun.git@20a78f62ae7ccfb040de02cbe97137fa8d366d1c#egg=freezegun
gherkin-official==29.0.0
humanize==4.12.2
hypothesis==6.130.5
idna==3.10
importlib_metadata==8.6.1
iniconfig==2.1.0
Mako==1.3.9
MarkupSafe==3.0.2
maya==0.6.1
mock==5.2.0
more-itertools==10.6.0
packaging==24.2
parse==1.20.2
parse_type==0.6.4
pendulum==3.0.0
pluggy==1.5.0
py==1.11.0
py-cpuinfo==9.0.0
pycparser==2.22
pytest==8.3.5
pytest-asyncio==0.26.0
pytest-bdd==8.1.0
pytest-benchmark==5.1.0
pytest-cov==2.9.0
pytest-cover==3.0.0
pytest-coverage==0.0
pytest-mock==3.14.0
pytest-randomly==3.16.0
pytest-xdist==3.6.1
python-dateutil==2.9.0.post0
pytz==2025.2
PyYAML==6.0.2
regex==2024.11.6
requests==2.32.3
requests-mock==1.12.1
responses==0.25.7
six==1.17.0
snaptime==0.2.4
sortedcontainers==2.4.0
time-machine==2.16.0
tomli==2.2.1
tomlkit==0.13.2
trustme==1.2.1
typing_extensions==4.13.0
tzdata==2025.2
tzlocal==5.3.1
urllib3==2.3.0
zipp==3.21.0

name: freezegun
channels:
  - defaults
  - https://repo.anaconda.com/pkgs/main
  - https://repo.anaconda.com/pkgs/r
  - conda-forge
dependencies:
  - _libgcc_mutex=0.1=main
  - _openmp_mutex=5.1=1_gnu
  - ca-certificates=2025.2.25=h06a4308_0
  - ld_impl_linux-64=2.40=h12ee557_0
  - libffi=3.4.4=h6a678d5_1
  - libgcc-ng=11.2.0=h1234567_1
  - libgomp=11.2.0=h1234567_1
  - libstdcxx-ng=11.2.0=h1234567_1
  - ncurses=6.4=h6a678d5_0
  - openssl=3.0.16=h5eee18b_0
  - pip=25.0=py39h06a4308_0
  - python=3.9.21=he870216_1
  - readline=8.2=h5eee18b_0
  - setuptools=75.8.0=py39h06a4308_0
  - sqlite=3.45.3=h5eee18b_0
  - tk=8.6.14=h39e8969_0
  - wheel=0.45.1=py39h06a4308_0
  - xz=5.6.4=h5eee18b_1
  - zlib=1.2.13=h5eee18b_1
  - pip:
      - atomicwrites==1.4.1
      - attrs==25.3.0
      - certifi==2025.1.31
      - cffi==1.17.1
      - charset-normalizer==3.4.1
      - coverage==7.8.0
      - coveralls==4.0.1
      - cryptography==44.0.2
      - dateparser==1.2.1
      - docopt==0.6.2
      - exceptiongroup==1.2.2
      - execnet==2.1.1
      - freezegun==0.3.12
      - gherkin-official==29.0.0
      - humanize==4.12.2
      - hypothesis==6.130.5
      - idna==3.10
      - importlib-metadata==8.6.1
      - iniconfig==2.1.0
      - mako==1.3.9
      - markupsafe==3.0.2
      - maya==0.6.1
      - mock==5.2.0
      - more-itertools==10.6.0
      - packaging==24.2
      - parse==1.20.2
      - parse-type==0.6.4
      - pendulum==3.0.0
      - pluggy==1.5.0
      - py==1.11.0
      - py-cpuinfo==9.0.0
      - pycparser==2.22
      - pytest==8.3.5
      - pytest-asyncio==0.26.0
      - pytest-bdd==8.1.0
      - pytest-benchmark==5.1.0
      - pytest-cov==2.9.0
      - pytest-cover==3.0.0
      - pytest-coverage==0.0
      - pytest-mock==3.14.0
      - pytest-randomly==3.16.0
      - pytest-xdist==3.6.1
      - python-dateutil==2.9.0.post0
      - pytz==2025.2
      - pyyaml==6.0.2
      - regex==2024.11.6
      - requests==2.32.3
      - requests-mock==1.12.1
      - responses==0.25.7
      - six==1.17.0
      - snaptime==0.2.4
      - sortedcontainers==2.4.0
      - time-machine==2.16.0
      - tomli==2.2.1
      - tomlkit==0.13.2
      - trustme==1.2.1
      - typing-extensions==4.13.0
      - tzdata==2025.2
      - tzlocal==5.3.1
      - urllib3==2.3.0
      - zipp==3.21.0
prefix: /opt/conda/envs/freezegun

tests/test_datetimes.py::test_time_ns
tests/test_datetimes.py::TestUnitTestClassDecoratorSubclass::test_class_name_preserved_by_decorator tests/test_datetimes.py::TestUnitTestClassDecoratorSubclass::test_class_decorator_works_on_unittest tests/test_datetimes.py::TestOldStyleClasses::test_direct_method tests/test_datetimes.py::TestOldStyleClasses::test_inherited_method tests/test_datetimes.py::UnfrozenInheritedTests::test_time_is_not_frozen tests/test_datetimes.py::FrozenInheritedTests::test_time_is_frozen tests/test_datetimes.py::TestUnitTestClassDecorator::test_class_decorator_works_on_unittest tests/test_datetimes.py::TestUnitTestClassDecorator::test_class_name_preserved_by_decorator tests/test_datetimes.py::Tester::test_class_decorator_wraps_callable_object_py3 tests/test_datetimes.py::Tester::test_the_class tests/test_datetimes.py::Tester::test_class_decorator_ignores_nested_class tests/test_datetimes.py::Tester::test_class_name_preserved_by_decorator tests/test_datetimes.py::Tester::test_still_the_same tests/test_datetimes.py::Tester::test_class_decorator_respects_staticmethod tests/test_datetimes.py::TestUnitTestClassDecoratorWithNoSetUpOrTearDown::test_class_decorator_works_on_unittest tests/test_datetimes.py::test_tz_offset_with_today tests/test_datetimes.py::test_time_localtime tests/test_datetimes.py::test_time_with_dst tests/test_datetimes.py::test_tz_offset tests/test_datetimes.py::test_zero_tz_offset_with_time tests/test_datetimes.py::test_decorator tests/test_datetimes.py::test_manual_increment_seconds tests/test_datetimes.py::test_old_date_object tests/test_datetimes.py::test_bad_time_argument tests/test_datetimes.py::test_time_gmtime tests/test_datetimes.py::test_tz_offset_with_time tests/test_datetimes.py::test_datetime_object tests/test_datetimes.py::test_manual_increment tests/test_datetimes.py::test_date_object tests/test_datetimes.py::test_generator_object tests/test_datetimes.py::test_decorator_wrapped_attribute tests/test_datetimes.py::test_lambda_object tests/test_datetimes.py::test_simple_api tests/test_datetimes.py::test_invalid_type tests/test_datetimes.py::test_move_to tests/test_datetimes.py::test_old_datetime_object tests/test_datetimes.py::test_real_strftime_fall_through tests/test_datetimes.py::test_strftime tests/test_datetimes.py::test_maya_datetimes tests/test_datetimes.py::test_calendar_timegm tests/test_datetimes.py::test_function_object tests/test_datetimes.py::test_timedelta_tz_offset tests/test_datetimes.py::test_time_with_microseconds tests/test_datetimes.py::test_context_manager tests/test_datetimes.py::test_nested_context_manager_with_tz_offsets tests/test_datetimes.py::test_datetime_date_method tests/test_datetimes.py::test_nested_context_manager tests/test_datetimes.py::test_isinstance_without_active tests/test_datetimes.py::test_nice_datetime tests/test_datetimes.py::test_isinstance_with_active tests/test_datetimes.py::test_freeze_with_timezone_aware_datetime_in_utc tests/test_datetimes.py::test_min_and_max tests/test_datetimes.py::test_freeze_with_timezone_aware_datetime_in_non_utc tests/test_datetimes.py::test_time_with_nested tests/test_datetimes.py::test_should_use_real_time
freezegun/api.py
freezegun/api.py