I'm not sure there is anything left on the table to decide here, but...

On Wed, Apr 17, 2019 at 7:56 AM Paul Ganssle <paul@ganssle.io> wrote:
“Local” is as poorly defined, and more likely to be misinterpreted, as “naive”.  Local to the machine the code is running on? Local to the user? Local to the data the user is working with?

In this case it is not poorly defined, it specifically means the context of the system time. I was not saying that I think naive datetimes should represent local time, I'm saying that whenever a naive datetime is treated as representing a specific time (as opposed to an abstract datetime for calendrical operations), it is interpreted as a system-local time.

That is  dangerous (or at least annoying) and not useful. In these modern days of networked computing the system-local time is highly unlikely to be relevant, an highly likely to be wrong for the use case at hand.

Example: when numpy.datetime64 was introduced, the author made the very reasonable assumption, that based on ISO 8601: "If no UTC relation information is given with a time representation, the time is assumed to be in local time." - then a ISO string without a offset is given is local, and it applied the machine local timezone to create a UTC time.

This was a pain in the #$%$ and not the least bit useful. For anything. It required a bunch of hacks and work arounds, and was ultimately changed.

I really like the concept of naive datetimes, it makes the point -- this thing known nothing about time zones. period, end of story. It does not represent "local time" because that is a very poorly defined concept. However, there are lots and lots of applications that punt on timezones (because they are a nightmare), and rather, assume that all teh datetime data in a a given application is in the same time zone, whatever that may be. So the offset needs to be checked/corrected on I/O -- kind of like text encodings :-).

It happens that UTC has no DST or other ugliness, to naive datetimes can be used quite well to represent UTC -- whether a datetime is UTC or naive is only relevant when you want to convert to another timezone -- the use-case for naive datetimes is for when the timezone handling happens away from the datetime object (at the applications I/O boundary) -- and in this use case, using naive datetimes of rUTC is very useful.

The point is that naive datetimes are, well, naive, so none of the rest of the datetime machinery should every make ANY assumptions about what timezone it might represent. But if it is going to, then UTC is the only one that is at all useful or reliable.

So if your local time is set to America/New_York, then you get:

In [7]: dt = datetime(2019, 4, 15, 12).astimezone(timezone.utc)                                                                            

In [8]: print(dt)                                                                                                                          
2019-04-15 16:00:00+00:00

This is the whole problem: "your local time" is poorly defined -- what if I'm in New York, but running on a JupyterLab system in Los Angeles?

If I had noticed tha astimezone did this, when it was introduced, I would have suggested that we NOT do that. But now it's there, I see the docstring:

In [17]: dt.astimezone?
Docstring: tz -> convert to local time in new timezone tz
Type:      builtin_function_or_method

I'd like to see that expanded a bit -- maybe:

tz -> convert to local time of the system on which python is running  in new timezone tz

I see that the full docs are pretty clear about this -- but even then, some omre caution would be in order.

"If self is naive, it is presumed to represent time in the system timezone."

I 'd like to see that up front and center.

If we has it to do again, I'd probably make it raise an exception with a naive datetime.

oh well.

Like I said, I don't really feel strongly about breaking backwards compatibility to doing this, but I do dispute that it is "very useful". It creates an implicit assumption about what the datetime represents that is contrary to what the language itself assumes and there's already a perfectly good mechanism for making those assumptions explicit - attaching the timezone.utc object to the datetime.

and then taking it off again if you want a naive datetime?

Looking back at the OP's example:

a = datetime.utcnow()
b = a.timestamp()
c = datetime.utcfromtimestamp(b)
assert a == b

fails.

I would suggest that the "problem" here is timestamp() :

datetime.timestamp()

    Return POSIX timestamp corresponding to the datetime instance. The return value is a float similar to that returned by time.time().
    Naive datetime instances are assumed to represent local time

There's that pesky local time thing again. I see a big note in there making my point.

Anyway, we're all for backward compatibility, so I'm not sure there's much to be done here -- though updating the docs to provide more caution might be in order.

If nothing else, every time the term "local time" is used, something like "the timezone set in the locale of the computer on which the code is running", or a less wordy version, would be good.

-CHB

 


Best,
Paul
_______________________________________________
Datetime-SIG mailing list -- datetime-sig@python.org
To unsubscribe send an email to datetime-sig-leave@python.org
https://mail.python.org/mailman3/lists/datetime-sig.python.org/
The PSF Code of Conduct applies to this mailing list: https://www.python.org/psf/codeofconduct/


--

Christopher Barker, Ph.D.
Oceanographer

Emergency Response Division
NOAA/NOS/OR&R            (206) 526-6959   voice
7600 Sand Point Way NE   (206) 526-6329   fax
Seattle, WA  98115       (206) 526-6317   main reception

Chris.Barker@noaa.gov