New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TimeFormatter broken for sub-second resolution #18478

nmartensen opened this Issue Nov 25, 2017 · 1 comment


None yet
2 participants

nmartensen commented Nov 25, 2017

Code Sample, a copy-pastable example if possible

%matplotlib inline
import pandas
import datetime as pydt

pandas.DataFrame({'A': 1}, index=[pydt.time(1, 1, 1, 1), pydt.time(1, 1, 1, 100)]).plot()

Problem description

The TimeFormatter code has several issues. The first is here:

us = int((x - s) * 1e6 - ms)

ms needs to be multiplied by 1e3, otherwise we'd be subtracting milliseconds from microseconds.

The next problem is here:

fmt += '.%6f'

The strftime format does not support the %6f notation. This needs to be %f, otherwise the result would be either a literal '%6f' in the output or a ValueError (invalid format string).

fmt += '.%3f'

Same problems, plus: '%f' means microseconds for strftime(), %3f cannot turn this into milliseconds.

And the last one:

return pydt.time(h, m, s, us).strftime(fmt)

This timestamp is missing the milliseconds entirely. (Assuming the fix to the microsecond calculation mentioned above.)

Expected Output

Correctly formatted time stamp strings as tick labels.

Solution Approaches

  1. Drop the TimeFormatter entirely (after checking if MPL already copes with pydt.time())
  2. Drop any sub-second resolution support from the TimeFormatter, as it was broken for a long time and nobody complained.
  3. Make it work correctly in the way it was most likely intended to work.

What do you think? I can set up a pull request for option 3 if that's the preferred solution.


This comment has been minimized.


jreback commented Nov 25, 2017

@jorisvandenbossche can comment, but .time() is not a first class object in pandas at all, you almost certainly want to use a Timedelta

df = pandas.DataFrame({'A': 1}, index=[pd.Timedelta("01:01:01.0001"), pd.Timedelta("01:01:01.001")])

works just fine.

@jreback jreback modified the milestones: 0.22.0, 0.21.1 Dec 9, 2017

@jreback jreback closed this in 75b97a7 Dec 21, 2017

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment