Skip to content
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

24:00 Hour in DateTime #54636

Closed
ingojanssen mannequin opened this issue Nov 15, 2010 · 9 comments
Closed

24:00 Hour in DateTime #54636

ingojanssen mannequin opened this issue Nov 15, 2010 · 9 comments
Assignees
Labels
extension-modules C modules in the Modules dir stdlib Python modules in the Lib dir type-feature A feature request or enhancement

Comments

@ingojanssen
Copy link
Mannequin

ingojanssen mannequin commented Nov 15, 2010

BPO 10427
Nosy @mdickinson, @abalkin, @ezio-melotti, @merwok

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:

assignee = 'https://github.com/abalkin'
closed_at = <Date 2013-08-04.19:50:47.223>
created_at = <Date 2010-11-15.14:37:58.783>
labels = ['extension-modules', 'type-feature', 'library']
title = '24:00 Hour in DateTime'
updated_at = <Date 2013-08-04.19:50:47.222>
user = 'https://bugs.python.org/ingojanssen'

bugs.python.org fields:

activity = <Date 2013-08-04.19:50:47.222>
actor = 'belopolsky'
assignee = 'belopolsky'
closed = True
closed_date = <Date 2013-08-04.19:50:47.223>
closer = 'belopolsky'
components = ['Extension Modules', 'Library (Lib)']
creation = <Date 2010-11-15.14:37:58.783>
creator = 'ingo.janssen'
dependencies = []
files = []
hgrepos = []
issue_num = 10427
keywords = []
message_count = 9.0
messages = ['121230', '121234', '121956', '121967', '121980', '121985', '121988', '121989', '133284']
nosy_count = 7.0
nosy_names = ['mark.dickinson', 'belopolsky', 'rbp', 'ezio.melotti', 'eric.araujo', 'cvrebert', 'ingo.janssen']
pr_nums = []
priority = 'normal'
resolution = 'rejected'
stage = 'resolved'
status = 'closed'
superseder = None
type = 'enhancement'
url = 'https://bugs.python.org/issue10427'
versions = ['Python 3.3']

@ingojanssen
Copy link
Mannequin Author

ingojanssen mannequin commented Nov 15, 2010

Short:
make the DateTime class and related also accept 24 for the hour instead of stopping at 23:59:59.

from the python doc:

"class datetime.datetime(year, month, day[, hour[, minute[, second[,
microsecond[, tzinfo]]]]])
The year, month and day arguments are required. tzinfo may be None, or
an instance of a tzinfo subclass. The remaining arguments may be ints
or longs, in the following ranges:
[...]
0 <= hour < 24
[...]
If an argument outside those ranges is given, ValueError is raised."

from http://en.wikipedia.org/wiki/ISO_8601 :

"ISO 8601 uses the 24-hour clock system. The basic format is
[hh][mm][ss] and the extended format is [hh]:[mm]:[ss].

  • [hh] refers to a zero-padded hour between 00 and 24 (where 24 is
    only used to notate midnight at the end of a calendar day).
    [...]
    Midnight is a special case and can be referred to as both "00:00" and
    "24:00". The notation "00:00" is used at the beginning of a calendar
    day and is the more frequently used. At the end of a day use "24:00".
    Note that "2007-04-05T24:00" is the same instant as "2007-04-06T00:00"
    (see Combined date and time representations below)."

The use of 24:00 is very comfortable when using hourly datasets, the
first set of a day is saved under 1:00, the fifth (4:00 to 5:00) under
5:00 and the last (23:00 - 24:00) under 24:00. No need to suddenly use
23:59:59 or 0:00 the next day.

Actually in another part of Python SQLlite's date and time functions accept and outputs the 24:00. Adding some Python to an existing database made me aware of the problem.

@ingojanssen ingojanssen mannequin added the type-feature A feature request or enhancement label Nov 15, 2010
@ezio-melotti ezio-melotti added the stdlib Python modules in the Lib dir label Nov 15, 2010
@abalkin
Copy link
Member

abalkin commented Nov 15, 2010

+1

Note that in Python, semi-open intervals are favored, but specifying the last hour of the day is awkward when using datetime (as OP mentioned) and impossible using just time. Using closed intervals is not a good work-around in many cases because it requires the user to be explicit about precision: is the last hour [23:00-23:59], [23:00:00-23:59:00], or [23:00:00.999999-23:59:00.999999]?

I offer to write the patch for the C implementation if someone comes up with a patch for datetime.py including tests.

@abalkin abalkin added the extension-modules C modules in the Modules dir label Nov 15, 2010
@abalkin abalkin self-assigned this Nov 15, 2010
@rbp
Copy link
Mannequin

rbp mannequin commented Nov 21, 2010

I was writing tests for this issue, when something struck me: ok, datetime(year, month, day, 24) is valid. But is datetime(year, month, day, 24, 1) valid? Or datetime(year, month, day, 24, 0, 0, 1)?

I would say those aren't valid, although that makes checking forvalid hour values slightly weird (as in not straightforward): 24 is valid if minutes, seconds and microseconds are all 0, but invalid otherwise.

What do you think?

@ingojanssen
Copy link
Mannequin Author

ingojanssen mannequin commented Nov 21, 2010

On Sun, Nov 21, 2010 at 7:24 PM, Rodrigo Bernardo Pimentel wrote:

I would say those aren't valid, although that makes checking forvalid hour values slightly weird
(as in not straightforward): 24 is valid if minutes, seconds and microseconds are all 0, but invalid
otherwise.

Indeed anything beyond 24:0:0 is invalid

ingo

@abalkin
Copy link
Member

abalkin commented Nov 21, 2010

On Sun, Nov 21, 2010 at 1:24 PM, Rodrigo Bernardo Pimentel
<[email protected]> wrote:
..

I was writing tests for this issue, when something struck me: ok, datetime(year, month, day, 24) is valid.
But is datetime(year, month, day, 24, 1) valid? Or datetime(year, month, day, 24, 0, 0, 1)?

As you make progress on the patch, you will face more questions. For
example, what should datetime(y, m, d, 24).date() return? date(y, m,
d) or date(y, m, d) + timedelta(1)? Should strptime() parse '24' as a
valid %H field? Similarly, should strftime() produce '24'? Is
datetime(y, m, d, 24) equal to datetime(y, m, d) + timedelta(1)? If
so, hash calculation should be special cased.

On your original question, I feel that hour=24 should be allowed
regardless of the other values. I would recommend, however, that you
review python-dev discussion about allowing second=60 (search for
"leap second"). Once you have a reference implementation you will
need to explain motivations behind your choices on python-dev.

@mdickinson
Copy link
Member

As you make progress on the patch, you will face more questions.

Well, if all that's wanted is for hour==24 to be legal on input, with the datetime object itself being automatically normalized at creation time, then the choices seem simple: e.g.,

For example, what should datetime(y, m, d, 24).date() return? date(y,
m, d) or date(y, m, d) + timedelta(1)?

The latter, since the two datetime objects would be indistinguishable...

Should strptime() parse '24' as a valid %H field?

I'd say yes, provided that any minute, second or subsecond fields are all zero.

FWIW, I'm in the camp that says hour==24 should only be legal if all values for smaller time units are zero.

If a datetime object created with 'hour==24' doesn't immediately normalize itself, then I agree there are going to be a lot of hairy questions...

@abalkin
Copy link
Member

abalkin commented Nov 21, 2010

On Sun, Nov 21, 2010 at 3:48 PM, Mark Dickinson <[email protected]> wrote:
..

Well, if all that's wanted is for hour==24 to be legal on input, with the datetime object
itself being automatically normalized at creation time, then the choices seem simple: ..

What about time objects? If we take the "normalized at creation time"
approach, time(24) may still be disallowed.

@mdickinson
Copy link
Member

What about time objects? If we take the "normalized at creation time"
approach, time(24) may still be disallowed.

Yes, I guess that would follow. That wouldn't bother me too much. :-)

@abalkin
Copy link
Member

abalkin commented Apr 8, 2011

Is there still interest in pursuing this? Normalizing out of bounds arguments to datetime constructor is easy, but rather pointless. It is trivial to implement this functionality using existing timedelta constructor:

def normdatetime(Y, M, D, h, m, s):
    return datetime(Y, M, D) + timedelta(hours=h, minutes=m, seconds=s)

It would be much more interesting to allow datetime objects to store ISO 8601 data without loss of information. It may be important to some applications that datetime(Y, M, D, 24).date() is date(Y, M, D) rather than the next day. Other applications may want to distinguish between datetime(Y, M, D, 24) and datetime(Y, M, D) + timedelta(1) in some other ways. For leap seconds accounting, normalizing ISO 8601 timestamps with seconds=60 to the next minute is certainly wrong. An application that is unfortunate enough to record data during a leap second would clearly want to distinguish that data from data recorded a second later.

I believe that from practical applications point of view, it would be best to allow storing hour=24 and second=60 in datetime structure and order the resulting objects in the same way as ISO 8601 strings are ordered alphabetically. In other words,

Y-M-D 24:00 < Y-M-D+1 00:00

and

Y-M-D 23:59:60 < Y-M-D+1 00:00:00.

There is no sane choice for subtraction operation involving these special values or for adding timedeltas to them. It is probably best to raise an exception in those cases.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
extension-modules C modules in the Modules dir stdlib Python modules in the Lib dir type-feature A feature request or enhancement
Projects
None yet
Development

No branches or pull requests

3 participants