python / cpython

The Python programming language
https://www.python.org
Other
63.14k stars 30.23k forks source link

Add timespec optional flag to datetime isoformat() to choose the precision #63674

Closed smontanaro closed 8 years ago

smontanaro commented 10 years ago
BPO 19475
Nosy @malemburg, @gvanrossum, @tim-one, @terryjreedy, @abalkin, @vstinner, @ezio-melotti, @berkerpeksag, @vadmium, @matrixise, @alessandrocucci
Files
  • issue19475.patch: Patch
  • issue19475_v2.patch: Patch
  • issue19475_v3.patch: Patch
  • issue19475_v4.patch: Patch v4
  • issue19475_v5.patch: Patch v5
  • issue19475_v6.patch: Patch v6
  • issue19475_v7.patch: Patch v7
  • issue19475_v8.patch: Patch v8
  • issue19475_v9.patch: Patch v9
  • issue19475_v10_datetime_time.patch: added timespec to time.isoformat
  • issue19475_v11.patch: Patch v11
  • issue19475_v12.patch
  • issue19475_v13.patch: added milliseconds format to timespec
  • issue19475_v14.patch: added milliseconds to documentation
  • issue19475_v15.patch
  • issue19475_v16.patch
  • issue19475_v17.patch
  • Note: these values reflect the state of the issue at the time it was migrated and might not reflect the current state.

    Show more details

    GitHub fields: ```python assignee = 'https://github.com/abalkin' closed_at = created_at = labels = ['extension-modules', 'easy', 'type-feature'] title = 'Add timespec optional flag to datetime isoformat() to choose the precision' updated_at = user = 'https://github.com/smontanaro' ``` bugs.python.org fields: ```python activity = actor = 'python-dev' assignee = 'belopolsky' closed = True closed_date = closer = 'python-dev' components = ['Extension Modules'] creation = creator = 'skip.montanaro' dependencies = [] files = ['40018', '40024', '40117', '41329', '41371', '41381', '41387', '41388', '41391', '41420', '41448', '41464', '41988', '41994', '42007', '42031', '42063'] hgrepos = [] issue_num = 19475 keywords = ['patch', 'easy'] message_count = 94.0 messages = ['201917', '201918', '201922', '201924', '201925', '201926', '201929', '201931', '201932', '201934', '201935', '201943', '202220', '202238', '202239', '202242', '202243', '202270', '202274', '202276', '202282', '221958', '221959', '247265', '247401', '247402', '247439', '247723', '247948', '256458', '256470', '256475', '256476', '256477', '256478', '256479', '256480', '256481', '256483', '256486', '256513', '256536', '256552', '256556', '256560', '256561', '256591', '256764', '256813', '256855', '256858', '256866', '256967', '256991', '257196', '257202', '257203', '257284', '257288', '257534', '258289', '258473', '258477', '258479', '258480', '258481', '258482', '258483', '258485', '258493', '260629', '260645', '260695', '260725', '260875', '260876', '260878', '261060', '261066', '261068', '261073', '261074', '261077', '261078', '261080', '261081', '261082', '261083', '261084', '261085', '261086', '261133', '261135', '261269'] nosy_count = 14.0 nosy_names = ['lemburg', 'gvanrossum', 'tim.peters', 'terry.reedy', 'belopolsky', 'vstinner', 'ezio.melotti', 'cvrebert', 'python-dev', 'berker.peksag', 'martin.panter', 'matrixise', 'jerry.elmore', 'acucci'] pr_nums = [] priority = 'normal' resolution = 'fixed' stage = 'resolved' status = 'closed' superseder = None type = 'enhancement' url = 'https://bugs.python.org/issue19475' versions = ['Python 3.6'] ```

    smontanaro commented 10 years ago

    I have a CSV file. Here are a few rows:

    "2013-10-30 14:26:46.000528","1.36097023829" "2013-10-30 14:26:46.999755","1.36097023829" "2013-10-30 14:26:47.999308","1.36097023829" "2013-10-30 14:26:49.002472","1.36097023829" "2013-10-30 14:26:50","1.36097023829" "2013-10-30 14:26:51.000549","1.36097023829" "2013-10-30 14:26:51.999315","1.36097023829" "2013-10-30 14:26:52.999703","1.36097023829" "2013-10-30 14:26:53.999640","1.36097023829" "2013-10-30 14:26:54.999139","1.36097023829"

    I want to parse the strings in the first column as timestamps. I can, and often do, use dateutil.parser.parse(), but in situations like this where all the timestamps are of the same format, it can be incredibly slow. OTOH, there is no single format I can pass to datetime.datetime.strptime() that will parse all the above timestamps. Using "%Y-%m-%d %H:%M:%S" I get errors about the leftover microseconds. Using "%Y-%m-%d %H:%M:%S".%f" I get errors when I try to parse a timestamp which doesn't have microseconds.

    Alas, it is datetime itself which is to blame for this problem. The above timestamps were all printed from an earlier Python program which just dumps the str() of a datetime object to its output CSV file. Consider:

    >>> dt = dateutil.parser.parse("2013-10-30 14:26:50")
    >>> print dt
    2013-10-30 14:26:50
    >>> dt2 = dateutil.parser.parse("2013-10-30 14:26:51.000549")
    >>> print dt2
    2013-10-30 14:26:51.000549

    The same holds for isoformat():

    >>> print dt.isoformat()
    2013-10-30T14:26:50
    >>> print dt2.isoformat()
    2013-10-30T14:26:51.000549

    Whatever happened to "be strict in what you send, but generous in what you receive"? If strptime() is going to complain the way it does, then str() should always generate a full timestamp, including microseconds. The above is from a Python 2.7 session, but I also confirmed that Python 3.3 behaves the same.

    I've checked 2.7 and 3.3 in the Versions list, but I don't think it can be fixed there. Can the __str and isoformat methods of datetime (and time) objects be modified for 3.4 to always include the microseconds? Alternatively, can the %S format character be modified to consume optional decimal point and microseconds? I rate this as "easy" considering the easiest fix is to modify __str and isoformat, which seems unchallenging.

    ezio-melotti commented 10 years ago

    See bpo-7342.

    bitdancer commented 10 years ago

    It may be simple but as Ezio has pointed out, it has already been rejected :)

    The problem with being generous in what you accept in this context is that the parsing is using a specific format string, and the semantics of that format string are based on external "standards" and are pretty inflexible.

    The pythonic solution, IMO, is to have datetime's constructor accept what its str produces. And indeed, exactly this has been suggested by Alexander Belopolsky in bpo-15873. So I'm going to close this one as a duplicate of that one.

    smontanaro commented 10 years ago

    I don't accept your conclusion. I understand that making %S consume microseconds or ".%f" be "optional" would be a load. What's the problem with forcing __str__ and isoformat to emit microseconds in all cases though? That would allow you to parse what they produce using existing code. No new constructor needed.

    The issue of sometimes emitting microseconds, sometimes not, is annoying, even beyond this issue. I think for consistency's sake it makes sense for the string version of datetime and time objects to always be the same length.

    bitdancer commented 10 years ago

    It's not my conclusion. It's Guido's and the other developers who designed datetime. Argue with them. (I'd guess it would be better argued on python-ideas rather than python-dev, but use your own judgement.)

    tim-one commented 10 years ago

    The decision to omit microseconds when 0 was a Guido pronouncement, back when datetime was first written. The idea is that str() is supposed to be friendly, and for the vast number of applications that don't use microseconds at all, it's unfriendly to shove ".000000" in their face all the time. Much the same reason is behind why, e.g., str(2.0) doesn't produce "2.0000000000000000".

    I doubt this will change. If you want to use a single format, you could massage the data first, like

    if '.' not in dt:
        dt += ".000000"
    smontanaro commented 10 years ago

    Okay, so no to __str__. What about isoformat?

    tim-one commented 10 years ago

    I don't know, Skip. Since .isoformat() and str() have always worked this way, and that was intentional, it's probably going to take a strong argument to change either.

    gvanrossum commented 10 years ago

    Well, I don't know if this sways anything, but I was probably responsible, and I think my argument was something about not all timestamp sources having microseconds, and not wanting to emit the ".000000" in that case. If I could go back I'd probably do something else; after all str(1.0) doesn't return '1' either. But that's water under the bridge; "fixing" this is undoubtedly going to break a lot of code.

    Maybe we can give isoformat() a flag parameter to force the inclusion or exclusion of the microseconds (with a default of None meaning the current behavior)?

    smontanaro commented 10 years ago

    The ultimate culprit here is actually the csv module. :-) It calls str() on every element it's about to write. In my applications which write to CSV files I can special case datetime objects.

    I will stop swimming upstream.

    bitdancer commented 10 years ago

    I suppose in an ideal world the csv module would have some sort of hookable serialization protocol, like the database modules do :)

    terryjreedy commented 10 years ago

    As I understand Guido's message, he reopened this to consider adding a new parameter.

    Given an existing csv file like that given, either Tim's solution or try: parse with microseconds except ValueError: parse without should work.

    abalkin commented 10 years ago

    +1 on adding an option to isoformat(). We already have an optional \<sep> argument, so the symmetry with __str__ is not complete. To make this option more useful, rather than implementing always_emit_microseconds=False flag, I would add a keyword argument 'precision' that would take ('hour'|'minute'|'second'|millisecond'|'microsecond') value.

    50dd80bd-dd7a-48d4-a662-bd23ebae05bc commented 10 years ago

    I would like to implement this feature. I already wrote the Python part. Is there anything else to decide?

    vstinner commented 10 years ago

    2013/11/5 Alexander Belopolsky \report@bugs.python.org\:

    +1 on adding an option to isoformat(). We already have an optional \<sep> argument, so the symmetry with __str__ is not complete. To make this option more useful, rather than implementing always_emit_microseconds=False flag, I would add a keyword argument 'precision' that would take ('hour'|'minute'|'second'|millisecond'|'microsecond') value.

    Hour precision is not part of the ISO 8601 standard.

    "resolution" is maybe a better name for the new parameter than "precision": http://www.python.org/dev/peps/pep-0418/#glossary

    The new parameter should be added to datetime.datetime.isoformat() but also datetime.time.isoformat().

    abalkin commented 10 years ago

    +1 on all Victor's points.

    I like 'resolution' because this is the term that datetime module uses already:

    >>> from datetime import *
    >>> datetime.resolution
    datetime.timedelta(0, 0, 1)

    There is a slight chance of confusion stemming from the fact that datetime.resolution is timedelta, but proposed parameter is a string.

    I believe ISO 8601 uses the word "accuracy" to describe this kind of format variations. I am leaning towards "resolution", but would like to hear from others. Here are the candidates:

    1. resolution
    2. accuracy
    3. precision

    (Note that "accuracy" is the shortest but "resolution" is the most correct.)

    malemburg commented 10 years ago

    On 05.11.2013 21:31, STINNER Victor wrote:

    2013/11/5 Alexander Belopolsky \report@bugs.python.org\: > +1 on adding an option to isoformat(). We already have an optional \<sep> argument, so the symmetry with __str__ is not complete. To make this option more useful, rather than implementing always_emit_microseconds=False flag, I would add a keyword argument 'precision' that would take ('hour'|'minute'|'second'|millisecond'|'microsecond') value.

    Hour precision is not part of the ISO 8601 standard.

    "resolution" is maybe a better name for the new parameter than "precision": http://www.python.org/dev/peps/pep-0418/#glossary

    The new parameter should be added to datetime.datetime.isoformat() but also datetime.time.isoformat().

    Since this ticket is about being able to remove the seconds fraction part, I think it's better to use a name that is not already overloaded with other meanings, e.g. show_us=False or show_microseconds=False.

    BTW: Have you thought about the rounding/truncation issues associated with not showing microseconds ?

    A safe bet is truncation, but this can lead to inaccuracies of up to a second. Rounding is difficult, since it can lead to a "60" second value showing up for e.g. 11:00:59.95 seconds, or the need to return "12:00:00" for 11:59:59.95.

    abalkin commented 10 years ago

    MAL: Have you thought about the rounding/truncation issues associated with not showing microseconds ?

    I believe it has to be the truncation. Rounding is better left to the user code where it can be done either using timedelta arithmetics or at the time source. I would expect that in the majority of cases where lower resolution printing is desired the times will be already at lower resolution at the source.

    malemburg commented 10 years ago

    On 06.11.2013 16:51, Alexander Belopolsky wrote:

    MAL: Have you thought about the rounding/truncation issues associated with not showing microseconds ?

    Sure, otherwise I wouldn't have mentioned it :-)

    mxDateTime always uses 2 digit fractions when displaying date/time values. This has turned out to be a good compromise between accuracy and usability. In early version, I used truncation, but that caused (too many) roundtrip problems, so I started using careful rounding in later versions:

    /* Fix a second value for display as string.

    Seconds are rounded to the nearest microsecond in order to avoid cases where e.g. 3.42 gets displayed as 03.41 or 3.425 is diplayed as 03.42.

    Special care is taken for second values which would cause rounding to 60.00 -- these values are truncated to 59.99 to avoid the value of 60.00 due to rounding to show up even when the indicated time does not point to a leap second. The same is applied for rounding towards 61.00 (leap seconds).

    The second value returned by this function should be formatted using '%05.2f' (which rounds to 2 decimal places).

    */

    This approach has worked out well, though YMMV.

    I believe it has to be the truncation. Rounding is better left to the user code where it can be done either using timedelta arithmetics or at the time source. I would expect that in the majority of cases where lower resolution printing is desired the times will be already at lower resolution at the source.

    In practice you often don't know the resolution of the timing source. Nowadays, the reverse of what you said is usually true: the source resolution is higher than the precision you use to print it.

    MS SQL Server datetime is the exception to that rule, with a resolution of 333ms and weird input "rounding":

    http://msdn.microsoft.com/en-us/library/ms187819.aspx

    For full seconds, truncation will add an error of +/- 1 second, whereas rounding only adds +/- 0.5 seconds. This is what convinced me to use rounding instead of truncation.

    abalkin commented 10 years ago

    I am afraid that the rounding issues may kill this proposal. Can we start with something simple? For example, we can start with show=None keyword argument and allow a single value 'microseconds' (or 'us'). This will solve the issue at hand with a reasonable syntax: t.isoformat(show='us'). If other resolutions will be required, we can later add more values and may even allow t.isoformat(show=2) to show 2 decimal digits.

    smontanaro commented 10 years ago

    I am afraid that the rounding issues may kill this proposal. Can we start with something simple? For example, we can start with show=None keyword argument and allow a single value 'microseconds' (or 'us'). This will solve the issue at hand with a reasonable syntax: t.isoformat(show='us'). If other resolutions will be required, we can later add more values and may even allow t.isoformat(show=2) to show 2 decimal digits.

    I don't think the meaning of this proposed show keyword argument should be overloaded as you suggest. If you show microseconds, just show all of them.

    Furthermore...

    If we go far enough back, my original problem was really that the inclusion of microseconds in csv module output was inconsistent, making it impossible for me to later parse those values in another script using a fixed strptime format. Since the csv module uses str() to convert input values for output, nothing you do to isoformat() will have any effect on my original problem.

    In my own code (where I first noticed the problem) I acquiesced, and changed this

    d["time"] = now

    to this:

    d["time"] = now.strftime("%Y-%m-%dT%H:%M:%S.%f")

    where "now" is a datetime object. I thus guarantee that I can parse these timestamps later using the same format. I realize the inclusion of "T" means my fields changed in other ways, but that was intentional, and not germane to this discussion.

    So, fiddle all you want with isoformat(), but do it right. I vote that if you want to add a show parameter it should simply include all fields down to that level, omitting any lower down. If people want to round or truncate things you can give them that option, returning a suitably adjusted, new datetime object. I don't think rounding, truncation, or other numeric operations should be an element of conversion to string form. This does not happen today:

    >>> import datetime
    >>> x = datetime.datetime.now()
    >>> x
    datetime.datetime(2013, 11, 6, 12, 19, 5, 759020)
    >>> x.strftime("%Y-%m-%d %H:%M:%S")
    '2013-11-06 12:19:05'

    (%S doesn't produce "06")

    Skip

    abalkin commented 10 years ago

    Here is some "prior art": GNU date utility has an --iso-8601[=timespec] option defined as

    ‘-I[timespec]’ ‘--iso-8601[=timespec]’ Display the date using the ISO 8601 format, ‘%Y-%m-%d’. The argument timespec specifies the number of additional terms of the time to include. It can be one of the following:

    ‘auto’ Print just the date. This is the default if timespec is omitted. ‘hours’ Append the hour of the day to the date. ‘minutes’ Append the hours and minutes. ‘seconds’ Append the hours, minutes and seconds. ‘ns’ Append the hours, minutes, seconds and nanoseconds. If showing any time terms, then include the time zone using the format ‘%z’.

    https://www.gnu.org/software/coreutils/manual/html_node/Options-for-date.html

    abalkin commented 10 years ago

    Based on GNU date "prior art", we can introduce timespec='auto' keyword argument with the following values:

    'auto' - (default) same as current behavior 'hours' - %H 'minutes' - %H:%M 'seconds' - %H:%M:%S 'us' - %H:%M:%S.%f

    vstinner commented 9 years ago

    'seconds' - %H:%M:%S 'us' - %H:%M:%S.%f

    'us' is not consistent with the datetime module: it should be 'microseconds.

    >>> datetime.datetime.now().second
    50
    >>> datetime.timedelta(seconds=1)
    datetime.timedelta(0, 1)
    
    >>> datetime.datetime.now().microsecond
    123710
    >>> datetime.timedelta(microseconds=1)
    datetime.timedelta(0, 0, 1)
    vstinner commented 9 years ago

    @acucci: Nice first try, but your patch contains multiple bugs.

    c7164467-54f8-4d7b-90dd-836b0822aef0 commented 9 years ago

    @haypo thanks for the review and the suggestions, I'll correct the code soon

    c7164467-54f8-4d7b-90dd-836b0822aef0 commented 9 years ago

    udloaded a new patch, hope i had all bugs fixed!

    berkerpeksag commented 9 years ago

    Thanks, Alessandro! I left some additional comments on Rietveld: https://bugs.python.org/review/19475/#ps15278

    c7164467-54f8-4d7b-90dd-836b0822aef0 commented 9 years ago

    uploaded a new patch!

    c7164467-54f8-4d7b-90dd-836b0822aef0 commented 8 years ago

    Please can I have an update on this? It's already 4 months old, I'd like to see it closed. :)

    gvanrossum commented 8 years ago

    I like the idea. I have one suggestion: can we add 'milliseconds' as an option too? And might a well add 'nanoseconds' too, for future-proofing. I suppose there isn't a real use case for 'hours' but it seems silly to leave it out. I expect that 'minutes' will be the most popular option, since HH:MM is the precision that most people care about for meetings and stuff.

    abalkin commented 8 years ago

    It looks like issue19475_v3.patch uses some fancy Unicode quotes in the docstrings and .rst docs. Please change them to ASCII.

    c7164467-54f8-4d7b-90dd-836b0822aef0 commented 8 years ago

    I can work on that, although I'll need help from some senior dev. The problem here is that millisecond and nanosecond seems not to be attributes of the datetime object. What about open a new issue if we have to add them? Is not about adding an optional flag anymore... Anyway, as I said, any help is appreciated!

    abalkin commented 8 years ago

    GvR> I suppose there isn't a real use case for 'hours' but it seems silly to leave it out.

    Shouldn't we also have 'none' to leave out the time component entirely?

    abalkin commented 8 years ago

    The problem here is that millisecond and nanosecond seems not to be attributes of the datetime object.

    millisecond = dt.microsecond // 1000
    
    nanosecond = 0  # until we add it to datetime.
    gvanrossum commented 8 years ago

    Actually, nanosecond = dt.microsecond*1000.

    I don't think we need 'none' -- you should just extract the date component and call its isoformat() method if that's what you want.

    On Tue, Dec 15, 2015 at 12:01 PM, Alexander Belopolsky \< report@bugs.python.org> wrote:

    Alexander Belopolsky added the comment:

    > The problem here is that millisecond and nanosecond seems not to be attributes of the datetime object.

    millisecond = dt.microsecond // 1000

    nanosecond = 0 # until we add it to datetime.

    ----------


    Python tracker \report@bugs.python.org\ \http://bugs.python.org/issue19475\


    abalkin commented 8 years ago

    Actually, nanosecond = dt.microsecond*1000.

    I was thinking in terms breaking the fractional part of say

    00:00:00.123456789

    into

    mili = 123
    micro = 456
    nano = 789

    but you are right, a correct analogy for dt.microsecond in this case will be nanosecond=123456789 or 123456000 until we start storing enough precision.

    abalkin commented 8 years ago

    I think timespec= option should also be added to the time.isoformat method.

    vadmium commented 8 years ago

    Alessandro, did you try running the test suite? It is broken for me. One of the bugs is that it now omits zero hours, minutes, and seconds in addition to microseconds. (Kind of the reverse of what the bug was originally about :).

    Other failures look like this:

    \====================================================================== ERROR: test_isoformat (test.datetimetester.TestDateTime) ----------------------------------------------------------------------

    Traceback (most recent call last):
      File "/media/disk/home/proj/python/cpython/Lib/test/datetimetester.py", line 1560, in test_isoformat
        timespec_error = self.time()
    AttributeError: 'TestDateTime_Pure' object has no attribute 'time'

    I will leave some review comments.

    vadmium commented 8 years ago

    The doc string in the C module needs updating.

    c7164467-54f8-4d7b-90dd-836b0822aef0 commented 8 years ago

    Thanks for all the comments, here and on Rietveld. I'll keep working on it. Hope to upload a new patch soon.

    c7164467-54f8-4d7b-90dd-836b0822aef0 commented 8 years ago

    Uploaded a new patch (v4): DONE:

    TODO:

    The doc string in the C module needs updating. Where? I guess "Macros to extract fields from datetime objects." in c-api/datetime.rst Tell me if I'm wrong

    I think timespec= option should also be added to the time.isoformat method. I'll do it when I'm sure that the datetime.isoformat method is correct.

    vadmium commented 8 years ago

    With patch v4 many tests still fail for me. How are you running the test suite? Some excerpts:

    File "/media/disk/home/proj/python/cpython/Lib/test/datetimetester.py", line 1567, in test_isoformat self.assertEqual(t.isoformat(timespec='milliseconds'), "0001-02-03T04:05:01.000") AssertionError: '0001-02-03T04:05:01.000000' != '0001-02-03T04:05:01.000'

    File "/media/disk/home/proj/python/cpython/Lib/test/datetimetester.py", line 2310, in test_isoformat self.assertEqual(t.isoformat(), "00:00:00") AssertionError: '00:00:00.000000' != '00:00:00'

    File "/media/disk/home/proj/python/cpython/Lib/test/datetimetester.py", line 2379, in test_str self.assertEqual(str(self.theclass(12, 2, 3, 0)), "12:02:03") AssertionError: '12:02:03.000000' != '12:02:03'

    The C module doc string I referred to is this one; I left a review comment at the source:

    >>> print(datetime.isoformat.__doc__)
    [sep] -> string in ISO 8601 format, YYYY-MM-DDTHH:MM:SS[.mmmmmm][+HH:MM].

    sep is used to separate the year from the time, and defaults to 'T'.

    c7164467-54f8-4d7b-90dd-836b0822aef0 commented 8 years ago

    I just did that...

    \~/Documenti/cpython$ ./configure --with-pydebug \~/Documenti/cpython$ make -s -j2 \~/Documenti/cpython$ ./python -m test -v datetimetester ... ...

    ---------------------------------------------------------------------- Ran 325 tests in 1.128s

    OK (skipped=1) 1 test OK.

    8977102d-e623-4805-b309-cd0ad35b0d72 commented 8 years ago

    Even that produces 3 failures on my setup, though the full list would be available when running: ./python -m test -v test_datetime

    It is obvious, however, that the tests would fail: you've changed "if us:" to "if us is None:".

    abalkin commented 8 years ago

    \~/Documenti/cpython$ ./python -m test -v datetimetester

    You shouldn't use "datetimetester" on the command line. Use "test_datetime" instead.

    vadmium commented 8 years ago

    If the timespec allowed any arbitrary number of digits after the decimal point, that would remove any argument about nanoseconds not being supported. It would also mean I could use this in one case where I currently format to two decimal places (my compromise between accurate timestamps and excessive information). Just a suggestion :)

    c7164467-54f8-4d7b-90dd-836b0822aef0 commented 8 years ago

    Uploaded a new patch.

    This time I ran tests using: $ ./python -m test -v test_datetime

    and got no errors.

    I've written the c docstring, updated docs, and rewrote _format_time function.

    I know it's boring review this another time, but I'm doing my best.

    Thanks to all.

    c7164467-54f8-4d7b-90dd-836b0822aef0 commented 8 years ago

    Uploaded a new patch after SilentGhost review comments.

    As he told me, I've left out milliseconds and nanoseconds, but refactored both python and c code so we could easily add support for them when they will be available.

    c7164467-54f8-4d7b-90dd-836b0822aef0 commented 8 years ago

    Sorry @SilentGhost, I didn't seen your comment at the bottom of the review. With this patch is microsecond is 0, the time will display 6 zeroes.