import pytest

from distutils.version import LooseVersion
import numpy
import pandas
import dateutil
import pandas.util._test_decorators as td


def pytest_addoption(parser):
    parser.addoption("--skip-slow", action="store_true",
                     help="skip slow tests")
    parser.addoption("--skip-network", action="store_true",
                     help="skip network tests")
    parser.addoption("--run-high-memory", action="store_true",
                     help="run high memory tests")
    parser.addoption("--only-slow", action="store_true",
                     help="run only slow tests")


def pytest_runtest_setup(item):
    if 'slow' in item.keywords and item.config.getoption("--skip-slow"):
        pytest.skip("skipping due to --skip-slow")

    if 'slow' not in item.keywords and item.config.getoption("--only-slow"):
        pytest.skip("skipping due to --only-slow")

    if 'network' in item.keywords and item.config.getoption("--skip-network"):
        pytest.skip("skipping due to --skip-network")

    if 'high_memory' in item.keywords and not item.config.getoption(
            "--run-high-memory"):
        pytest.skip(
            "skipping high memory test since --run-high-memory was not set")


# Configurations for all tests and all test modules

@pytest.fixture(autouse=True)
def configure_tests():
    pandas.set_option('chained_assignment', 'raise')


# For running doctests: make np and pd names available

@pytest.fixture(autouse=True)
def add_imports(doctest_namespace):
    doctest_namespace['np'] = numpy
    doctest_namespace['pd'] = pandas


@pytest.fixture(params=['bsr', 'coo', 'csc', 'csr', 'dia', 'dok', 'lil'])
def spmatrix(request):
    from scipy import sparse
    return getattr(sparse, request.param + '_matrix')


@pytest.fixture
def ip():
    """
    Get an instance of IPython.InteractiveShell.

    Will raise a skip if IPython is not installed.
    """

    pytest.importorskip('IPython', minversion="6.0.0")
    from IPython.core.interactiveshell import InteractiveShell
    return InteractiveShell()


is_dateutil_le_261 = pytest.mark.skipif(
    LooseVersion(dateutil.__version__) > LooseVersion('2.6.1'),
    reason="dateutil api change version")
is_dateutil_gt_261 = pytest.mark.skipif(
    LooseVersion(dateutil.__version__) <= LooseVersion('2.6.1'),
    reason="dateutil stable version")


@pytest.fixture(params=[None, 'gzip', 'bz2', 'zip',
                        pytest.param('xz', marks=td.skip_if_no_lzma)])
def compression(request):
    """
    Fixture for trying common compression types in compression tests
    """
    return request.param


@pytest.fixture(params=[None, 'gzip', 'bz2',
                        pytest.param('xz', marks=td.skip_if_no_lzma)])
def compression_no_zip(request):
    """
    Fixture for trying common compression types in compression tests
    except zip
    """
    return request.param

pandas/conftest.py
import pytest

from distutils.version import LooseVersion
import numpy
import pandas
import dateutil
import pandas.util._test_decorators as td


def pytest_addoption(parser):
    parser.addoption("--skip-slow", action="store_true",
                     help="skip slow tests")
    parser.addoption("--skip-network", action="store_true",
                     help="skip network tests")
    parser.addoption("--run-high-memory", action="store_true",
                     help="run high memory tests")
    parser.addoption("--only-slow", action="store_true",
                     help="run only slow tests")


def pytest_runtest_setup(item):
    if 'slow' in item.keywords and item.config.getoption("--skip-slow"):
        pytest.skip("skipping due to --skip-slow")

    if 'slow' not in item.keywords and item.config.getoption("--only-slow"):
        pytest.skip("skipping due to --only-slow")

    if 'network' in item.keywords and item.config.getoption("--skip-network"):
        pytest.skip("skipping due to --skip-network")

    if 'high_memory' in item.keywords and not item.config.getoption(
            "--run-high-memory"):
        pytest.skip(
            "skipping high memory test since --run-high-memory was not set")


# Configurations for all tests and all test modules

@pytest.fixture(autouse=True)
def configure_tests():
    pandas.set_option('chained_assignment', 'raise')


# For running doctests: make np and pd names available

@pytest.fixture(autouse=True)
def add_imports(doctest_namespace):
    doctest_namespace['np'] = numpy
    doctest_namespace['pd'] = pandas


@pytest.fixture(params=['bsr', 'coo', 'csc', 'csr', 'dia', 'dok', 'lil'])
def spmatrix(request):
    from scipy import sparse
    return getattr(sparse, request.param + '_matrix')


@pytest.fixture
def ip():
    """
    Get an instance of IPython.InteractiveShell.

    Will raise a skip if IPython is not installed.
    """

    pytest.importorskip('IPython', minversion="6.0.0")
    from IPython.core.interactiveshell import InteractiveShell
    return InteractiveShell()


is_dateutil_le_261 = pytest.mark.skipif(
    LooseVersion(dateutil.__version__) > LooseVersion('2.6.1'),
    reason="dateutil api change version")
is_dateutil_gt_261 = pytest.mark.skipif(
    LooseVersion(dateutil.__version__) <= LooseVersion('2.6.1'),
    reason="dateutil stable version")


@pytest.fixture(params=[None, 'gzip', 'bz2', 'zip',
                        pytest.param('xz', marks=td.skip_if_no_lzma)])
def compression(request):
    """
    Fixture for trying common compression types in compression tests
    """
    return request.param


@pytest.fixture(params=[None, 'gzip', 'bz2',
                        pytest.param('xz', marks=td.skip_if_no_lzma)])
def compression_no_zip(request):
    """
    Fixture for trying common compression types in compression tests
    except zip
    """
    return request.param


@pytest.fixture(scope='module')
def datetime_tz_utc():
    from datetime import timezone
    return timezone.utc

pandas/conftest.py
diff --git a/doc/source/whatsnew/v0.23.0.txt b/doc/source/whatsnew/v0.23.0.txt
index 72f63a4da0f4d..b6316bd39f396 100644
--- a/doc/source/whatsnew/v0.23.0.txt
+++ b/doc/source/whatsnew/v0.23.0.txt
@@ -729,6 +729,7 @@ Timezones
 - Bug in :func:`DatetimeIndex.insert` where inserting ``NaT`` into a timezone-aware index incorrectly raised (:issue:`16357`)
 - Bug in the :class:`DataFrame` constructor, where tz-aware Datetimeindex and a given column name will result in an empty ``DataFrame`` (:issue:`19157`)
 - Bug in :func:`Timestamp.tz_localize` where localizing a timestamp near the minimum or maximum valid values could overflow and return a timestamp with an incorrect nanosecond value (:issue:`12677`)
+- Bug when iterating over :class:`DatetimeIndex` that was localized with fixed timezone offset that rounded nanosecond precision to microseconds (:issue:`19603`)
 
 Offsets
 ^^^^^^^
diff --git a/pandas/_libs/tslib.pyx b/pandas/_libs/tslib.pyx
index 85e667521e5f2..fec7f21d6e6eb 100644
--- a/pandas/_libs/tslib.pyx
+++ b/pandas/_libs/tslib.pyx
@@ -46,7 +46,8 @@ from tslibs.timezones cimport (is_utc, is_tzlocal, is_fixed_offset,
                                treat_tz_as_pytz, get_dst_info)
 from tslibs.conversion cimport (tz_convert_single, _TSObject,
                                 convert_datetime_to_tsobject,
-                                get_datetime64_nanos)
+                                get_datetime64_nanos,
+                                tz_convert_utc_to_tzlocal)
 from tslibs.conversion import tz_convert_single
 
 from tslibs.nattype import NaT, nat_strings, iNaT
@@ -144,12 +145,12 @@ def ints_to_pydatetime(ndarray[int64_t] arr, tz=None, freq=None,
                 if value == NPY_NAT:
                     result[i] = NaT
                 else:
-                    dt64_to_dtstruct(value, &dts)
-                    dt = create_datetime_from_ts(value, dts, tz, freq)
-                    dt = dt + tz.utcoffset(dt)
-                    if box:
-                        dt = Timestamp(dt)
-                    result[i] = dt
+                    # Python datetime objects do not support nanosecond
+                    # resolution (yet, PEP 564). Need to compute new value
+                    # using the i8 representation.
+                    local_value = tz_convert_utc_to_tzlocal(value, tz)
+                    dt64_to_dtstruct(local_value, &dts)
+                    result[i] = func_create(value, dts, tz, freq)
         else:
             trans, deltas, typ = get_dst_info(tz)
 
diff --git a/pandas/conftest.py b/pandas/conftest.py
index 4fe66d4cf7e1f..37f0a2f818a3b 100644
--- a/pandas/conftest.py
+++ b/pandas/conftest.py
@@ -93,3 +93,9 @@ def compression_no_zip(request):
     except zip
     """
     return request.param
+
+
+@pytest.fixture(scope='module')
+def datetime_tz_utc():
+    from datetime import timezone
+    return timezone.utc
diff --git a/pandas/tests/indexes/datetimes/test_timezones.py b/pandas/tests/indexes/datetimes/test_timezones.py
index 075d239df5f7a..62854676d43be 100644
--- a/pandas/tests/indexes/datetimes/test_timezones.py
+++ b/pandas/tests/indexes/datetimes/test_timezones.py
@@ -17,7 +17,7 @@
 import pandas as pd
 from pandas._libs import tslib
 from pandas._libs.tslibs import timezones
-from pandas.compat import lrange, zip
+from pandas.compat import lrange, zip, PY3
 from pandas import (DatetimeIndex, date_range, bdate_range,
                     Timestamp, isna, to_datetime, Index)
 
@@ -949,6 +949,17 @@ def test_dti_union_aware(self):
         result = rng.union(rng2)
         assert result.tz.zone == 'UTC'
 
+    @pytest.mark.parametrize('tz', [None, 'UTC', "US/Central",
+                                    dateutil.tz.tzoffset(None, -28800)])
+    @pytest.mark.usefixtures("datetime_tz_utc")
+    @pytest.mark.skipif(not PY3, reason="datetime.timezone not in PY2")
+    def test_iteration_preserves_nanoseconds(self, tz):
+        # GH 19603
+        index = DatetimeIndex(["2018-02-08 15:00:00.168456358",
+                               "2018-02-08 15:00:00.168456359"], tz=tz)
+        for i, ts in enumerate(index):
+            assert ts == index[i]
+
 
 class TestDateRange(object):
     """Tests for date_range with timezones"""

DateTimeIndex.__iter__().next() rounds time to microseconds, when timezone aware
#### Code Sample

```python
>> import pandas as pd
>> datetimeindex = pd.DatetimeIndex(["2018-02-08 15:00:00.168456358"])
>> datetimeindex
DatetimeIndex(['2018-02-08 15:00:00.168456358'], dtype='datetime64[ns]', freq=None)
>> datetimeindex = datetimeindex.tz_localize(datetime.timezone.utc)
>> datetimeindex
DatetimeIndex(['2018-02-08 15:00:00.168456358+00:00'], dtype='datetime64[ns, UTC+00:00]', freq=None)
>> datetimeindex.__getitem__(0)
Timestamp('2018-02-08 15:00:00.168456358+0000', tz='UTC+00:00')
>> datetimeindex.__iter__().__next__()
Timestamp('2018-02-08 15:00:00.168456+0000', tz='UTC+00:00')
```
#### Problem description

When using localize DateTimeIndex with nanosecond precision, __getitem__ behavious differs from __iter__().__next__ behaviour, as when iterating thought the DateTimeIndex the date is round to microseconds. This doen not happends if the DatetimeIndex has no timezone.

#### Output of ``pd.show_versions()``

<details>

INSTALLED VERSIONS
------------------
commit: None
python: 3.4.2.final.0
python-bits: 64
OS: Linux
OS-release: 4.9.0-0.bpo.2-amd64
machine: x86_64
processor: 
byteorder: little
LC_ALL: None
LANG: en_US.UTF-8
LOCALE: en_US.UTF-8

pandas: 0.22.0
pytest: None
pip: 9.0.1
setuptools: 36.5.0
Cython: None
numpy: 1.14.0
scipy: 1.0.0
pyarrow: None
xarray: None
IPython: 6.2.1
sphinx: None
patsy: None
dateutil: 2.6.1
pytz: 2017.3
blosc: None
bottleneck: None
tables: None
numexpr: None
feather: None
matplotlib: 2.0.2
openpyxl: None
xlrd: None
xlwt: None
xlsxwriter: None
lxml: None
bs4: None
html5lib: None
sqlalchemy: None
pymysql: None
psycopg2: None
jinja2: None
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: None

</details>

