Repository: pandas-dev/pandas
Pull request: TST #24444 added tests
At last, there are no issues at all. I've made a new PR.

- [x] closes #24444
- [x] tests added / passed
- [x] passes `black pandas`
- [x] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`


Problem statement:
Imprecision when converting Period to timestamp
#### Code Sample, a copy-pastable example if possible

```python
pd.Period("2000-12-31 23:59:59.999").to_timestamp()
```
returns: 2000-12-31 23:59:59.998999999
instead of 2000-12-31 23:59:59.999
It works correctly for other dates, e.g.
```python
pd.Period("2000-12-31 23:59:59.99").to_timestamp()
```
returns correctly "2000-12-31 23:59:59.990000"

#### Problem description
incorrect conversion of Period to Timestamp, see above.

#### Expected Output

#### Output of ``pd.show_versions()``

<details>

INSTALLED VERSIONS
------------------
commit: None

pandas: 0.23.4
pytest: None
pip: 18.1
setuptools: 39.1.0
Cython: None
numpy: 1.15.4
scipy: 1.2.0
pyarrow: None
xarray: None
IPython: 7.2.0
sphinx: None
patsy: 0.5.1
dateutil: 2.7.5
pytz: 2018.7
blosc: None
bottleneck: None
tables: None
numexpr: None
feather: None
matplotlib: 3.0.2
openpyxl: None
xlrd: None
xlwt: None
xlsxwriter: None
lxml: None
bs4: None
html5lib: None
sqlalchemy: None
pymysql: None
psycopg2: None
jinja2: 2.10
s3fs: None
fastparquet: None
pandas_gbq: None
pandas_datareader: None

</details>

Hints from issue discussion:
on master. looks ok to me
```
In [10]: p = pd.Period('2000-12-31 23:59:59.99')

In [11]: p.freq
Out[11]: <Milli>

In [12]: pd.Period('2000-12-31 23:59:59.99').to_timestamp()
Out[12]: Timestamp('2000-12-31 23:59:59.990000')

In [13]: pd.Period('2000-12-31 23:59:59.99').to_timestamp(how='end')
Out[13]: Timestamp('2000-12-31 23:59:59.990999998')

In [14]: pd.Period('2000-12-31 23:59:59.99').to_timestamp(how='start')
Out[14]: Timestamp('2000-12-31 23:59:59.990000')

In [15]: pd.Period('2000-12-31 23:59:59.99').to_timestamp(how='end') - pd.Period('2000-12-31 23:59:59.99').to_timestamp(how='start')
    ...: 
Out[15]: Timedelta('0 days 00:00:00.000999')
```

@mkuklik can you explain why you think this should be different
That is correct, pd.Period('2000-12-31 23:59:59.99').to_timestamp() works file.
The issue is with (three 9's at the end)
```python
pd.Period('2000-12-31 23:59:59.999').to_timestamp()
```

I wonder if this is symptomatic of an intrinsic Python rounding issue?
this also looks fine to me

```
In [1]: p = pd.Period('2000-12-31 23:59:59.999')

In [2]: p.to_timestamp()
Out[2]: Timestamp('2000-12-31 23:59:59.998999999')

In [3]: p.to_timestamp().round('1 ms')
Out[3]: Timestamp('2000-12-31 23:59:59.999000')

In [4]: p.to_timestamp(how='end') - p.to_timestamp(how='start')
Out[4]: Timedelta('0 days 00:00:00.001000')
```
How is it fine if 2000-12-31 23:59:59.998999999 != 2000-12-31 23:59:59.999

this conversion should be consistent across all the values without having
to round up in some cases.


On Sun, Dec 30, 2018 at 1:26 PM Jeff Reback <notifications@github.com>
wrote:

> this also looks fine to me
>
> In [1]: p = pd.Period('2000-12-31 23:59:59.999')
>
> In [2]: p.to_timestamp()
> Out[2]: Timestamp('2000-12-31 23:59:59.998999999')
>
> In [3]: p.to_timestamp().round('1 ms')
> Out[3]: Timestamp('2000-12-31 23:59:59.999000')
>
> In [4]: p.to_timestamp(how='end') - p.to_timestamp(how='start')
> Out[4]: Timedelta('0 days 00:00:00.001000')
>
> —
> You are receiving this because you were mentioned.
> Reply to this email directly, view it on GitHub
> <https://github.com/pandas-dev/pandas/issues/24444#issuecomment-450578282>,
> or mute the thread
> <https://github.com/notifications/unsubscribe-auth/AFjHo6ogXIq-MGZkovc3Dvh_RP4yHu2Nks5u-QVggaJpZM4ZiHl7>
> .
>

@mkuklik you are welcome to have a look. I would say we are round tripping thru floats; these are natively int64.
Looks to work on master now. Could use a test

```
In [4]: pd.Period('2000-12-31 23:59:59.999').to_timestamp()
   ...:
Out[4]: Timestamp('2000-12-31 23:59:59.999000')

In [5]: pd.__version__
Out[5]: '1.1.0.dev0+1536.ga7fb88fd5'
```
Hello, 

I've went through examples and review my tests. I think indeed it is not solved.
I think there are issues with `microsecond` == 10^-6s and `nanosecond` == 10^-9s.


```
In [1]: Period("2000-12-31 23:59:59.999999").to_timestamp(freq='ms').microsecond
Out[1]: 999000
```
expected was `999999`
```
In [2]: Period("2000-12-31 23:59:59.123456", freq='ms').to_timestamp().microsecond
Out[2]: 123000
```
expected was `123456`
```
In [3]: Period("2000-12-31 23:59:59.123456").to_timestamp().microsecond
Out[3]: 123456
```
This last example is working, if I do not give the `freq` argument.

Perhaps another bug, the `nanosecond` is not throwing any warning, but always return `0`:
```
In [4]: Period("2000-12-31 23:59:59.123456789").to_timestamp().nanosecond
Out[4]: 0
```

Commit message: TST #24444 added tests

Patch to review:
diff --git a/pandas/tests/scalar/period/test_period.py b/pandas/tests/scalar/period/test_period.py
index 42bd20fd9640b..e6b2db6ccde9e 100644
--- a/pandas/tests/scalar/period/test_period.py
+++ b/pandas/tests/scalar/period/test_period.py
@@ -649,6 +649,26 @@ def test_to_timestamp_business_end(self):
         expected = pd.Timestamp("1990-01-06") - pd.Timedelta(nanoseconds=1)
         assert result == expected
 
+    @pytest.mark.parametrize(
+        "ts, expected",
+        [
+            ("1970-01-01 00:00:00", 0),
+            ("1970-01-01 00:00:00.000001", 1),
+            ("1970-01-01 00:00:00.00001", 10),
+            ("1970-01-01 00:00:00.499", 499000),
+            ("1999-12-31 23:59:59.999", 999000),
+            ("1999-12-31 23:59:59.999999", 999999),
+            ("2050-12-31 23:59:59.5", 500000),
+            ("2050-12-31 23:59:59.500001", 500001),
+            ("2050-12-31 23:59:59.123456", 123456),
+        ],
+    )
+    @pytest.mark.parametrize("freq", [None, "us", "ns"])
+    def test_to_timestamp_microsecond(self, ts, expected, freq):
+        # GH 24444
+        result = Period(f"{ts}").to_timestamp(freq=freq).microsecond
+        assert result == expected
+
     # --------------------------------------------------------------
     # Rendering: __repr__, strftime, etc
 


Code review comments:
diff_hunk: @@ -649,6 +649,26 @@ def test_to_timestamp_business_end(self):
         expected = pd.Timestamp("1990-01-06") - pd.Timedelta(nanoseconds=1)
         assert result == expected
 
+    @pytest.mark.parametrize(
+        "ts, expected",
+        [
+            ("1970-01-01 00:00:00", 0),
+            ("1970-01-01 00:00:00.000001", 1),
+            ("1970-01-01 00:00:00.00001", 10),
+            ("1970-01-01 00:00:00.499", 499000),
+            ("1999-12-31 23:59:59.999", 999000),
+            ("1999-12-31 23:59:59.999999", 999999),
+            ("2050-12-31 23:59:59.5", 500000),
+            ("2050-12-31 23:59:59.500001", 500001),
+            ("2050-12-31 23:59:59.123456", 123456),
+        ],
+    )
+    @pytest.mark.parametrize("freq", [None, "us", "ns"])
+    def test_to_timestamp_microsecond(self, ts, expected, freq):
+        # GH 24444
+        result = Period(f"{ts}").to_timestamp(freq=freq).microsecond
path: pandas/tests/scalar/period/test_period.py
text: @user1:
Is the f-string necessary here?
```suggestion
        result = Period(ts).to_timestamp(freq=freq).microsecond
```

@author:
It is not !, a new PR was sent.