Brian Lovin
/
Hacker News
Daily Digest email

Get the top HN stories in your inbox every day.

kerkeslager

I've noted before and will note again that the amount of hate Python got for the 2-to-3 deprecations has led to a much worse problem: piecemeal low-visibility updates which are much harder to plan for.

As a contractor, I singlehandedly migrated 4 different codebases from 2 to 3; a total of just under a million lines of code, and none of these codebases took more than 40 hours. This was not some horrific burden for most companies using Python. The people who flamed Python for these breaking changes were either extreme outliers or the sort of people who would be happy with the language never making breaking changes, ever, no matter how bad of mistakes in design were discovered.

I would strongly prefer that datetime.utcnow were not deprecated in a 3.x release, but instead deprecated along with the GIL and any other breaking changes, in Python 4.0. Yes, it would get them flamed. And the flamers are wrong. At least that way people can plan for the transition at their leisure instead of constantly worrying that a 3.x release will unexpectedly break their codebase if they don't read the release notes before every update.

Wowfunhappy

> The people who flamed Python for these breaking changes were either extreme outliers or the sort of people who would be happy with the language never making breaking changes, ever, no matter how bad of mistakes in design were discovered.

Count me in the "don't make breaking changes" camp. You can spit out warnings to prevent developers from using certain language features in new code, but changes which outright break old code should be extremely rare.

This is how Javascript works (the language, not the ecosystem around it), and it means I can update my web browser and continue visiting old websites.

I don't think most languages should go as far as Javascript. However, the case for a breaking change should be a heck of a lot stronger than "we think all timestamps should have timezones now." That's a fine opinion to have, but it doesn't mean you should go break stuff.

derefr

> However, the case for a breaking change should be a heck of a lot stronger than "we think all timestamps should have timezones".

How about if you rephrase the case as "we've sampled codebases that use naive timestamps, and at least 50% of them had critical bugs related to mistaken assumptions made about timezones by functions used to produce vs consume those timestamps. Your code is already broken. This update just makes the compiler force you to rewrite your code in a way that makes the errors obvious and/or into type errors — and, therefore, which forces you to fix those bugs."

Wowfunhappy

Presumably this code works for me if I'm using it. In most cases, an imperfect program I can run is better than one I can't run. Yes there are exceptions.

In the ideal case, the author updates their code so it keeps working. But what if I'm not the author and know nothing about the codebase? Is forcing me to make a naïve change to get things working again more likely to remove bugs or add them?

The compiler can warn me that I probably have a bug and should change my code. But it shouldn't hold the program hostage until I comply.

This isn't a blanket statement in favor of permissive compilers. It's fine for the compiler to force good practices the first time. I just have a problem with the compiler going back and changing its mind later.

ledauphin

I don't know if I agree or disagree with your general thesis, but it has to be pointed out that the JavaScript ecosystem is even more complex than Python -- despite the fact that it doesn't have to deal with a C ABI -- and I think this is in fact largely because the language has resisted change so much that everything has just moved beyond the language itself to some form of transpilation.

The world changes. Software development changes. The best way to guarantee that your entire codebase will become an obsolete monolith that eventually needs to get replaced is to make sure that you choose an ecosystem that isn't growing and changing too.

Yes, there are COBOL and Fortran and whatever else programs still running out there. But software is not mostly a "one and done" thing, and unless you're confident you're writing something that's "one and done", then these comparisons are truly irrelevant.

josephg

> I think this is in fact largely because the language has resisted change so much that everything has just moved beyond the language itself to some form of transpilation

Resisted change? JavaScript has changed massively in the last 12 years I’ve been using it. Promises, generator functions, es modules, webassembly, const/let, arrow functions, destructing, classes, iterators, you name it. The fact that JavaScript is also a compilation target isn't because JavaScript doesn’t change much. It’s because the web is so important, and people wanted to use new JavaScript features before they became widely available in browsers.

kerkeslager

> Count me in the "don't make breaking changes" camp. You can spit out warnings to prevent developers from using certain language features in new code, but changes which outright break old code should be extremely rare.

"Extremely rare" != "never".

> This is how Javascript works (the language, not the ecosystem around it), and it means I can update my web browser and continue visiting old websites.

...and there are reasons for this which don't apply to Python. A typical JavaScript deployment needs to run on millions of machines which the developer doesn't control, and coordinating an update of a JavaScript version to all the machines it needs to run on isn't feasible. Python is usually not run under these constraints: in the typical case, Python runs on servers which the person running it on controls.

JavaScript pays an extremely high cost for this, continuing to support decades-old horrible misfeatures such as nonsensical typecasts, returning undefined from nonexistent members, and a variety of incompatible ways to make asynchronous calls. You shouldn't do this unless you have a very strong reason to do so, and these misfeatures is one of the main reasons you shouldn't use JavaScript unless you have a strong reason to do so.

devjab

Did they break stuff? One of the differences is that Python is versioned, so you should be capable of running your current version without issues and then update when you’re ready.

While JavaScript itself is backwards compatible, in a few cases beyond good reason, it’s not really backwards compatible for most of its modern use cases. Node isn’t backwards compatible and neither is TypeScript, and neither are many frameworks as you point out.

I do agree that making breaking changes shouldn’t become a thing, but at some points you also have to move things forward. That being said, I do think this particular case is a shift in philosophy more so than a step forward, since this is a far more opinionated change than what may have been the case previously in Python.

Kwpolska

You may not always be in control of the Python version, for example if you depend on the Python provided by your OS. You may also want to use a newer Python version for its features, support (bugfixes) and libraries, so you'll need to rewrite things.

Java also has versions, but they generally don't remove things. You can keep your ugly code and use the latest version of the language.

kobalsky

> Did they break stuff? One of the differences is that Python is versioned, so you should be capable of running your current version without issues and then update when you’re ready.

the problem is that the amount of asinine changes and unnecessary shuffling of standard libraries is so consistent that a good number of libraries have a grid of compatibility with different Python versions.

So version 1.1.0 is compatibe python 3.8, 3.9 and 3.10 and version 1.2.0 is compatible with python => 3.11 (until the next breaking change is introduced), you have to pick and choose depending on which python version you are using, and sometimes you have impossible combinations and pip enters an almost never ending loop trying to find combinations of libraries that work with each other.

I've been developing, packaging and creating our own deployment tooling since python 2.2 and I cannot believe how Python devs are still shuffling stuff around instead of working on fixing package management.

dheera

Deprecation shouldn't break peoples' code all of a sudden. Code should still work, and just get more annoying over time. Initially, spit out warnings that deprecation is going to happen. Then, start changing the user's desktop background. Then, start playing nice cat meowing sounds out of the speaker. Then, start playing ghastly wailing sounds out of the speaker. Then, start sending e-mails. Then, scan for IoT light bulbs and mess with the colors. Then, scan for bluetooth headsets within a 50 meter radius and play wailing noises out of those. Then, impose a 0.001 second delay. Then a 0.01 second delay. Then a 0.1 second delay. Then a 1.0 second delay. Then start scraping LinkedIn for engineer resumes and e-mail them to any sysadmin e-mails you can find in the various config files in /etc/ and /home/.

Don't suddenly deprecate stuff and break people's code on a moment's notice. Most likely the person who wrote the code using the deprecated function was laid off 2 years ago and the company still depends on it.

panarky

> Don't suddenly deprecate stuff and break people's code on a moment's notice.

"Deprecated" doesn't mean "break people's code on a moment's notice".

FTA: "datetime.datetime’s utcnow() and utcfromtimestamp() are deprecated and will be removed in a future version"

"likely a few years out"

"once you switch to Python 3.12 or newer you will start seeing deprecation messages on your console and your logs, and these can get annoying"

dheera

> will be removed in a future version

It should not be "removed" as a step function. It should get more annoying over time but still function for the next 30 years, at which point it's incredibly, incredibly annoying to call the function (but still works).

This helps products continue running but simultaneously incentivizes the people on top to hire engineers to make the code less annoying without completely wrecking the business or downstream software that depends on it.

Basically, the servers will still run and the customers will be happy but if the VP sitting 50m from the servers doesn't want cat noises coming out of their headphones they need to hire an engineer ASAP or it will turn into wailing noises pretty soon.

> you will start seeing deprecation messages on your console and your logs, and these can get annoying

Not annoying enough. This only sends messages to someone who was probably got laid during the recession and isn't around anymore, or some open source repo creator who is now being forced to work 18 hours a day by their new job and doesn't have the energy to update any code. It needs to slowly creep out and annoy other people nearby before someone will actually care. When the neighbors constantly have wailing noises coming out of their living room TV they will be incentivized to contribute to the repo.

Clamchop

A typical pattern is to deprecate in minor versions and remove in the next major version, encouraging gentle readiness for that major update. I don't know enough about Python to say this is what they're doing, but it fits in this case.

OJFord

That's not what they do, in semver terms you get breaking changes in minor version bumps.

To be fair, as a result there's maybe more resistance to making any such change than there otherwise would be, but in nicher standard lib modules there are API/semantic changes from one version to another.

I'd prefer semver, like it sounds GP would, but failing that I'd prefer totally owning that the version is fairly meaningless, and doing something like 2023.x as pip does for example. At least then everyone knows they should check for anything like that. (Not to mention it carries the additional age/potentially out of date information.)

selcuka

> something like 2023.x as pip does

Not sure what you mean by that. The version of pip currently installed on my laptop is 23.3.1. Did you mean some other package, such as pytz?

xorcist

The only reason this is a potential source of bugs is because of the poorly thought out changes in Python 3. It is not a problem with Python 2 code, and it wouldn't have been a problem should there have been backwards compatible types in Python 3.

What's done is done, and the best way to avoid this is to add support in linters to warn for this, or a runtime warning when that can be done safely. Deprecating or removing a method is madness for any language with any real world use.

The only thing that leads to is a lot of unnecessary work for a lot of people, and there will be a best practice to save old versions of the interpreter to run old software.

ensignavenger

Deprecating is not removing. Deprecating a method breaks nothing. It just shows a deprecation warning when you use it and have deprecation warnings turned on.

Kwpolska

A deprecation in Python will be followed by removal a few years from now (where a few ≈ 2 in recent practice).

mkesper

And that's a good thing! Do not hold on to broken cruft but give some time (more than just a few months (Ansible and other culprits) but definitely less tan 10 years (Python 3 transition)) for code maintainers to handle it.

akra

For Python that is properly source controlled, audited and understood I do agree it isn't that hard to port. However unlike many more compiled languages there's probably a LOT of python code out there that isn't which makes changes to Python and its APIs more risky. Don't get me wrong - this is one of the reasons why the language is popular - it is seen as "easy and approachable"; you just write a script and it works for the most part. It also was often the only language built into many distro's other than bash making it ultra convenient.

Which means a lot of it written isn't catalogued, in source control, whatever but still doing stuff people need and often forgotten about. This makes changes of Python IMO more risky. I've seen Python scripts on old Linux images lurking in the wild working for even decades without people realizing they are there set up by non-dev's people back in the day. Another example would be some financial analyst coding a script to produce reports that are used to make decisions and need same behavior each time - one day the date time function maybe in this article will just stop working often with the original person who wrote it just to get stuff done quick long gone.

IMO migration from 2 to 3 was particularly painful for Python because of the way it/was is used, historically who the main users of it, its popularity (wide blast radius) and how it is often Python is updated by blanket system upgrades given it is standard on many machines. Being aware of what needs to be upgraded for a given large scale environment is most of the work.

cdogl

The problem is open source. I generally agree with your analysis of the migration path, but who’s going to go through every open source library and do this grunt work? It comes at a huge cost however you swing it, and it’s not theoretical: I recall trying to switch to Python 3 over and over during those dark years only to find an essential library couldn’t support it.

upbeat_general

Yeah this is the real reason right here.

Updating your code: Easy. Updating 10 different libraries that you depend on but don't know anything about: Not so easy

saaspirant

Can you share some nuggets about how did you migrate a bigger codebase from 2 to 3 in less than 40 hours?

I tried with a Django codebase and didn't know where to go.. 2to3 tools they provided didn't help much. Can you give steps involved? I'll dig deeper on each step. Thanks

kerkeslager

In general the approach is pretty heavily dependent on a trustworthy test suite. If you don't have that, you'll have to write a lot of tests which will take more than 40 hours, but... Python is pretty heavily dependent on having a trustworthy test suite.

All of the codebases I migrated were Django codebases.

Basically, I would:

1. Upgrade to the latest 2.x, run the test suite and a bunch of manual tests, and fix any errors/warnings. 2. Upgrade all the dependencies one by one to versions that support version 3, run the test suite and the manual tests, and fix any errors/warnings. This was generally the hardest part, because some projects had imported a lot of bleeding edge nonsense which was abandoned before Python 3 support was implemented, so I had to a) encapsulate the dependency, and then b) rewrite the encapsulated functionality either with my own code, or with a more up-to-date library. This is a predictable result of importing nonsense, and I blame the developers who did that, not the Python team. 3. Upgrade to 3.x, run the test suite of manual tests, and fix any errors/warnings.

vegabook

I suspect a lot of financial data code is going to break. I've worked on a number of codebases where the explicit instructions were "everything is UTC, all the time", and enforced at the entry edges of the code. Bringing in timezones was a definite NO for reasons of the unholy mess this would inevitably create:

* India has half-hour timezones

* Countries change their DST rules all the time.

* Conversion between timezones is an utter mess.

As Wes McKinney once said about python datetime: "Welcome to Hell"[0]

[0] https://stackoverflow.com/a/13753918

albert_e

> India has half-hour timezones

Not plural though;

The whole of India -- even though it is pretty vast in area -- has a single time-zone country-wide. I am very thankful for this. We already have a lot of other challenges -- including dozens of different languages -- that a single time zone is a relief.

But yes -- the +5:30 offset usually makes for a less-than-ideal factor to plan meetings or follow non local event schedules.

Did I mention we also hate the Summertime / Daylight Saving time adjustments we have to accommodate twice a year when working with western teams -- more adjustment even after most people have already sacrificed on a sane 9-5 schedule to ensure they overlap with EU/US teams for daily work meetings. We cant imagine why US that has multiple time-zones already in a single country, and EU whose countries are often smaller than states in India ... need so much adjustment. Why can't they, for instance, simply declare that school/offices open at 10am instead of 9am for six designated months every year instead of imposing this adjustment on the entire world.

mulmen

> We cant imagine why US that has multiple time-zones already in a single country

Are you aware the contiguous United States is three times larger than India? Alaska alone is half the size of India and not at the same longitude as the lower 48. Hawaii is even farther west than most of Alaska. The easternmost point in the US is 66 degrees west. The westernmost is 179 degrees west. That’s nearly a third of the globe and I'm not even including territories.

> Why can't they, for instance, simply declare that school/offices open at 10am instead of 9am for six designated months every year instead of imposing this adjustment on the entire world.

Is this a serious comment? Europe doesn’t have a central government. The most recent attempt to establish one was extremely unpopular and famously stopped in 1945.

Why should foreign schools and businesses change their hours to accommodate you? A more obvious solution would be to just stop observing DST but that’s not something that will happen unilaterally and will be an especially hard sell at extreme latitudes.

If you want to do business internationally you have to deal with timezones. India isn’t unique in that inconvenience.

Asooka

> but that’s not something that will happen unilaterally and will be an especially hard sell at extreme latitudes.

Not unilaterally per se, but EU parliament did vote to end it in ... 2021 https://www.europarl.europa.eu/news/en/press-room/20190321IP... . COVID kind of put those plans on the backburner.

People at extreme latitudes should not care much, since for them DST does close to nothing.

The parent's proposal is actually quite sound. It would be a lot more useful to have institutions switch their starting times for part of the year when it makes sense for them, rather than forcing a one-size-fits-all solution on everyone. Countries at different latitudes would be free to switch e.g. school start times at different dates depending on when sunlight shifts too far in one direction, while keeping their clocks synchronised with astronomical time. Heck, Spain basically does that already, since they're on the wrong timezone (geography dictates they should be on British time, but because of events in the '40s, they're on Central European time) - so they do everything one hour "later".

albert_e

I was not arguing for a single timezone nor surprised that US has multiple timezones. the surprise was that even after multiple timezones, they need so much adjustment twice a year -- which is what I was arguing against. (to be more specific the argument was against how they go about that adjustment -- not that an adjustment is needed which is understandably due to geography and seasons)

you quoted half my sentence which creates an easy strawman.

> A more obvious solution would be to just stop observing DST

yes that is essentially my argument too ...with an extra accommodation for folks who will argue about seasons causing wild changes in sunrise / sunset / daylight.

sznio

> The most recent attempt to establish one was extremely unpopular and famously stopped in 1945.

that's one way to say it

eru

> A more obvious solution would be to just stop observing DST but that’s not something that will happen unilaterally and will be an especially hard sell at extreme latitudes.

Huh, why would it not happen unilaterally? Different countries already fiddle with their daylight savings times (or absence thereof) unilaterally, and the start of DST is not synchronised across the globe anyway.

So if you have two countries that start DST on different weeks that's already a hassle to deal with, and one of them going off DST altogether doesn't really add any extra hassle in their bilateral dealings.

postmodest

"We cant imagine why US that has multiple time-zones already in a single country"

Because "The USA" spans from GMT+10 to GMT-10. Your Solar Noon only varies by an hour between Kolkata and Mumbai. Without time zones, the continental U.S. would see a solar noon difference of three and a half hours. And that's not including Alaska, Hawaii, and Guam, which gives us a 20 hour span. You want all those places to be in the same time zone?

albert_e

please read my post again.

I was not arguing for a single time zone.

you quoted only half of my sentence and are arguing against a strawman.

crote

Greenland has a single timezone for a 4-hour span. China has a single timezone for a 5-hour span. Having a single timezone for the contiguous US would definitely not be unheard of.

Guam is a bit of an odd duck because it is on the other side of the date line. The US currently spans from UTC-4 in Puerto Rico to UTC+10 in Guam - which is essentially the same as UTC-14. That's a 10-hour span, not a 20-hour one. Still, excluding the minor overseas colonial possessions would probably make the most sense.

phantom784

> Why can't they, for instance, simply declare that school/offices open at 10am instead of 9am for six designated months every year instead of imposing this adjustment on the entire world.

If they did that, you'd still be stuck shifting your schedule when they change their working hours.

albert_e

Not necessarily.

In the most simplest scenario -- once a recurring meeting is fixed at 10:30 AM eastern STANDARD time, say, -- no schedule change is needed all-year-long if we dont tamper with the clock.

It is just that US worker -- due to their own convenience -- decides to show up in their office at 9AM for six months and 10am for other other six months of the year. Recurring meeting does not need to change at all.

The adjustment , if any, is all on US side. And for local season / climate reasons which has nothing to do with the remote team members, and so the remote team members elsewhere in the world dont need to change anything at all.

Just dont tamper with the clock and things will be much more simple.

>> If they did that, you'd still be stuck shifting your schedule when they change their working hours.

No -- we do not want to link our meetings to the changing office hours. We just want a fixed time on a clock fixed clock. Pick a time that works throughout the year for both teams. Like 10.30 AM EST in my example above.

Current the meetings are "fixed time" but on a moving clock -- in reality the meetings shift around but US folks move their clocks to "simulate" for themselves that they are always having their daily meeting "at 10AM" -- they achieve this illusion by inflicting pain on themselves as well as rest of the world. We would love if they can leave us out of this forced dance :)

gaganyaan

That's a good thing, and way better than the current state of things. Let the federal government pick summer/winter hours, and everyone can adjust or not as they see fit.

pixl97

If you live closer to the equator it may not make much sense. For the longest time the population of the US was heavily biased to it's more northern populations than it's more southern. In relation to someone that lives in Delhi someone in Maine will see a 4 hour larger swing in day length. If you're talking farther south in India, like Madurai the size of the swing will be even larger.

2143

> Why can't they, for instance, simply declare that school/offices open at 10am instead of 9am for six designated months every year instead of imposing this adjustment on the entire world.

Or, if you extrapolate this argument further, you could even wonder why the entire world can't run on a single timezone.

But here's the problem: for example, imagine it's UTC everywhere on Earth. No local timezones.

As per your solution, people in India can go to sleep at 4:30 pm (UTC), wake up at 12:30 am, have lunch at 7:30 am etc.

Likewise, people in San Francisco can go to bed at 6 am, wake up at 2 pm, have lunch at 9 pm etc.

Now, the problem is, when someone wants to setup an international meeting or whatever, nobody would have a clear idea or whether it would be "sleeping time" for any of the participants involved, without having to look it up.

Like, with the current setup, it's kind of universally understood that 3 am local time is sleeping time, hence people would avoid setting up meetings at that time.

But if everywhere on Earth it's the same time such as UTC, I would have no idea if 3 am UTC is your sleeping time or lunch time or whatever. I would have to maintain lookup tables of when the sleep time, lunch time etc would be for every country as per UTC.

Similar problems exist (to a lesser degree) when large countries move to a single timezone.

Yes there are flaws in the existing setup, but moving to a single timezone for large countries would only introduce a new set of challenges.

albert_e

My comment is being misread as an argument for a single timezone for all of USA.

Kindly re-read.

I was arguing against daylight savings adjustments twice an year. Not against having multiple timezones per country / region. My comment was simply that timezones should be sufficient without the need for DST.

What I said ...

>> We cant imagine why US that has multiple time-zones already in a single country, and EU whose countries are often smaller than states in India ... need so much adjustment.

Simplified ...

>> cant imagine why US, and EU need so much adjustment.

Pardon any poor punctuation.

saagarjha

Don't you still need to look up times when you schedule with people?

screye

Having lived in both India and far North in the USA, I'd take half-hour time zones over daylight savings (switches) every time.

Shifting time-zones increases car accidents by about 6-16% for the entire week (studies vary). Just that is a massive enough impact on safety and productivity to discourage the switch. At a personal level, leaving work at 5.30-ish with it being pitch black outside, is among the most depressing things in the world. Even more wasteful is that the average American wakes up at 7.20am. So, they don't gain any daylight but lose an entire hour.

I'm not usually the type to make such accusations, so I apologize in advance for sounding culture-warry. But, switching-time zones is "white person thing". Large percent of the Chinese, Indian & the Middle Eastern population live above the 25th parallel (Florida) and large populations of Korea & Japan live north of the Bay Area without daylight-switching.

Permanent daylight time with later sunrise would be a huge win.

2143

> Why can't they, for instance, simply declare that school/offices open at 10am instead of 9am for six designated months every year instead of imposing this adjustment on the entire world.

Or, if you extrapolate this argument further, you could even wonder why the entire world can't run on a single timezone. Like, it can be UTC everywhere.

People in India can go to sleep at

steveBK123

Brazil's stock market does/used to do something along these lines when US & Brazil changed their clocks in opposite direction, to keep the NY time hours of the Brazilian exchange from drifting as far. Given that we all also observed DST at the time, this made things even more complicated for systems.

jagged-chisel

For sharing between systems and representing dates to humans debugging a system, the following has worked well …

Planned local events: future date and time string including local time zone

Planned global events: future date and time string in UTC, with UTC timezone

Past events: date and time string in UTC with UTC time zone, unless there is a strong case to be made that these should be localized (see “planned local events” above)

Strings in the format specified by ISO-8601.

Of course, internal representation can be whatever it needs to be for efficiency. For example, maybe your database stores as integer microseconds since an epoch. Fine, but as soon as that leaves the database, ISO-8601 that date.

theK

I like your premise but disagree with your guidance.

You should not convert the integer early, you should actually wait until the very last moment.

Nowadays a timestamp will be marshalled and demashalled by (at the very least) two runtimes until it reaches human eyeballs opening up a wide spectrum of bug potential, difficult to understand code and development slowdowns. Keeping it simple and unambiguous is very important. Time libraries have a habit of coming and going, ints are always there and 99% of the date arithmetic is trivial any way.

Don't use a lib, just pretty print numbers and you'll be fine.

fluoridation

An int is not unambiguous, though. "2023-11-19T14:22:34-03:00" is clearly a timestamp and represents an unambiguous point in time, while a number by itself doesn't mean anything. You have to know that it's a timestamp (probably from context) and you have to know what timezone it's in.

Izkata

> Past events: date and time string in UTC with UTC time zone, unless there is a strong case to be made that these should be localized (see “planned local events” above)

I don't think there's any case for storing local time with past events. They happened at a specific date and time, store them in UTC and if needed convert to local on display. Plus, though it's a rare circumstance, for one hour each year DST switches cause a duplicate hour - so local time is ambiguous during that hour.

Ndymium

There is, when you aggregate your data to create graphs such as "My most active hours", you will have a problem if your user moves between timezones, if you did not store the actual local wall time. [0] For those cases, you can store the offset or the denormalized local time along with the UTC version.

[0] https://blog.nytsoi.net/2022/03/13/utc

Hamuko

I'd say that wouldn't enforcement be rather simple going forwards since you could just enforce that dt.tzinfo == datetime.timezone.utc, but as far as I know, timezone information checking in Python can be a bit of a pain.

  >>> utc1 = datetime.timezone.utc
  >>> utc2 = zoneinfo.ZoneInfo("UTC")
  >>> utc1 == utc2
  False
  >>> dt1 = datetime.datetime.now(utc1)
  >>> dt2 = datetime.datetime.now(utc2)
  >>> dt1.tzinfo == dt2.tzinfo
  False

notatoad

Removing utcnow() doesn't force you to use tz-aware dates though. That's just a leap that the author of this article has made.

If you're working in a system where all dates are utc, then datetime.now() gets you a date in utc and you don't need datetime.utcnow(). The only reason to call utcnow is if you're working on a system where the local timezone isn't utc, so you inherently have to deal with timezones at some level. Which means that using naive timestamps is a bad idea.

nerdponx

datetime.now(tz=timezone.utc) is what you probably want most of the time anyway. You can always manually strip off the time zone component if you really want to use datetimes without associated time zones.

plibither8

> India has half-hour timezones

If that's messy, consider Nepal's timezone that's on the 45-minute mark (UTC+5:45).

poink

Last startup I worked for hired a Nepal-based QA person. There was a bunch of calendaring and daily/weekly charts in the apps, and she found bugs in _everything_.

I make sure to test with Nepal time whenever I'm testing date/time stuff now.

iso8859-1

Even better, use Monrovia in the 70s. They had an offset of 44m30s.[0]

    >>> datetime(1972,1,1,tzinfo=ZoneInfo('Africa/Monrovia')).isoformat()
    '1972-01-01T00:00:00-00:44:30'
[0]: https://en.wikipedia.org/wiki/Time_in_Liberia#History

lb1lf

And, of course, there's the (hopefully apocryphal) story of the French initially referring to GMT as 'Paris time minus nine minutes and twenty-one seconds'.

midasuni

When I built a live clock for some new CasparCG based graphics for a major TV program out of singapore some years back, a colleague reviewing it in London tried to trick it with a Nepal offset — apparently they’d run into an issue with the Viz system they used in 2015 when there were a lot of lives from Nepal.

Obviously it worked fine, as did Chatham Island.

hprotagonist

or one island of new zealand (chatham), which is +12:45

slyall

The Chatham Islands are an Island group, two of which are inhabited (Chatham Island and Pitt Island).

https://en.wikipedia.org/wiki/Chatham_Islands

Right now is it on +13:45 due to Daylight Saving

https://en.wikipedia.org/wiki/Chatham_Standard_Time_Zone

angrygoat

or along the highway near the Western Australia/South Australia border, which informally uses +8:45 https://en.wikipedia.org/wiki/UTC%2B08:45

Izkata

RealLifeLore just had a video about time zones in that area of the world, there's an area between New Zealand and Hawaii where you can go north/south and jump an entire day.

scheme271

Nepal is UTC+5:45. I think that's the largest population on a 15/45 minute offset.

PartiallyTyped

Why is humanity like this?

hn72774

It's mostly political.

There isn't a perfect geographical width for time zones. So humans pick something to define the boundaries between time zones. And making boundaries on a map is political.

inglor_cz

In Europe, a huge driver for standardization of timezones into "reasonable" slots was railway traffic, including cross-border traffic.

Railways are extremely sensitive to exact time and, indeed, the very concept of unified time across the entire region or country only started developing when railways expanded across Europe. Prior to that, individual towns were happy with their own local solar time, but once railway connections were introduced, time irregularities would cause chaos at best and carnage at worst. That led to introduction of unified railway time which developed to timezones as we know them.

Railways aren't as prominent nowadays as they were 100-150 years ago, and countries like Nepal and India don't have extensive, frequently used cross-border railways anyway; any cross-border traffic is sporadic and mostly freight. So there is one fewer reason to cooperate with your neighbors when it comes to time-related issues. Trucks can take weird timezone changes just fine.

bandrami

In this case it was so the Sun would be roughly due south at noon in Delhi

svilen_dobrev

because humanity never understood time properly.. so all these facades making it look "simpler" while actualy a lot more complicated.

long time ago there was a special `$ man date` -like page in linux which went into long explaining many "amazing" things about calendar stuff, like whoever feudal in 1553 deciding that certain week was bad and striked it out of his and his country's calendar, or another one that liked certain month and decided to repeat it...

but cannot find it anymore.

ahoka

Then accept that UTC is a timezone and just use that everywhere. There are also a lot of things that can’t be easily stored in UTC, like opening hours.

rtpg

Something like “9AM-5PM EST” can’t be stored in a datetime object even with a timezone slot! Datetimes with a timezone represent specific points in time, not vague “5PM” like concepts.

MrJohz

I feel like every time a discussion on timezones comes up, people compete to come up with different situations where "see, your perfect system can't work, we should give up on timezones entirely".

Here, I'm not even sure what your point is. A datetime object cannot capture a range, no, just like a number can't capture a range of values. But through the magic of having two of them, we can get easily create a data structure containing two datetimes to represent a range. 5pm is not a vague concept, it is the time 5pm, the hour that typically comes after 4pm and before 6pm. If your point is that you can't store only a time in a datetime object, that's true, that's why the standard library also provides the `time` object which represents a time.

Where things might get a bit more complex is if you want to store the time of a recurring event that should occur at the same time on multiple days for a given timezone. In this situation, you can typically use a naive time object to represent a wall clock time, plus the timezone that the user has requested. This way you still have all the raw information to decide when the event will happen in the future. (Note however, that the same time can occur multiple times on the same day, for example during daylight savings changes.)

narrator

Yeah, the stock market opens at what time EST? Including daylight saving time, etc. I agree that any time time goes to a serialized format over a socket or to a database or file it should always be UTC.

tsimionescu

UTC (or Unix timestamp, or any other non-localized date-time format) doesn't work for future localized events. It's fundamentally impossible to say what will be the UTC timestamp which corresponds to 9AM in some particular location in the future: the timezone of that location could arbitrarily change between now and then. Countries and smaller areas often experiment with such changes, wars happen and conquerors/liberators change the time etc.

So, when possible, it's best to store (future) human events in a localized datetime string. For things like physical events, the opposite is true of course - you can't say what will be the local date and time when the Sun will hit high noon over Athens 10 years from now, but you can certainly calculate the UTC timestamp for that.

briHass

Ignoring holidays/weekends: always 9:30AM or (0930) EST. Same with EDT: 9:30AM.

The key here is that the timezone info includes the daylight/standard designation. Or, in the ISO format -4:00 or -5:00 from UTC.

I think you meant to put ET (Eastern Time), which is still 9:30AM, but without a date associated with that time, there's no way to convert that to UTC or other timezones that don't have the same daylight saving time schedule.

icholy

Why can't opening hours be stored in UTC?

RichieAHB

A store’s opening hours will probably remain 9am-5pm regardless of any time zone changes around it. If you run a bunch of stores across time zones you need to know where each store is and whether it’s summer or winter to work backwards to find out 9-5 in UTC.

mulmen

The coffee shop in my neighborhood is open from 6am to 2pm Pacific. We observe daylight saving time. The shop hours do not change. So, what UTC value do you store?

bilsbie

I guess it would change based on local time changes.

pjot

Seems like the ideal way to store them to me!

jomoho

Every heard of daylight savings time (DST)?

Spivak

You still keep everything in UTC in this new world, it's just the object you use internally now knows that it's UTC and makes it so you can't accidentally do calculations on two naive datetimes which happen to be in different timezones.

You get to have the typing help you enforce that everything is in UTC.

konschubert

And you have to treat the timezone offset as information-free.

As in, 02:00+00:00 and 04:00+02:00 are absolutely equivalent representations of the same data.

If you need to know the timezone in which to display a time, you save that timezone separately

Buttons840

How do you express "our stores, across 6 different timezones, all open at 9:30 AM local time" in UTC?

sillysaurusx

That code runs in the context of humans. Therefore it needs to take humans into account when running.

This is a bit like asking "how do you represent a string length in utf-8?" The answer is, you don’t. It’s almost never a problem in practice.

Just like there is almost never a reason to care about the number of characters in a string, it’s very difficult to imagine that this code comes up in practice. But if it did, the code is simple: for a given timezone, is the current time in utc past 9:30am? If so, the store is open.

undefined

[deleted]

Buttons840

Let's say you host a store front for many businesses and it's decided that your customers, who are businesses, some with many stores, want to store a default opening time. Something along the lines of "All Home Depot's open a 6 AM, all Lowes open at 7 AM."

joshspankit

If someone expresses it that way it will be a huge hassle the moment they decide one store opens at a different time.

Buttons840

So maybe individual stores can customize their opening time, but corporate still wishes to store a default. How do you represent the default? How do you handle the DST time changes for individual stores?

I'm trying to poke holes in the "always use UTC and you're good" advice. I have actually encountered this scenario, and I didn't know how to apply that advice.

d0mine

utc is for a specific moment in time (deterministic with great precision for everyday use).

"9:30am local time" may be ambiguous/unknown (the rules may not exist yet)

Using the same programming type for both may cause confusion.

How do you express geographic coordinates? Noon in London and in NY are different moments in time (it may be important if you want to have a remote meeting).

samus

No need for something as brittle as geographic coordinates or addresses. Time Zone names are the right abstraction. A given location very rarely [edit: adopts another] time zone (unless in case of annexations, handovers of territory, etc.), but time zone rules (zone offset from UTC, DST, etc.) change all the time. A consequence of this is that the time zone database of applications should be updated every few months!

remram

"9:30 AM every day" is not a datetime. It's a time.

Footkerchief

Postgres stores this as TIMESTAMP WITHOUT TIME ZONE, sometimes called wall-clock time. IMO this is a good convention -- treating "ideal times" and specific epoch moments as two different types -- and more languages should support this (ideally with a less confusing label).

kevindamm

Elixir does as well, with NaiveDatetime

JJMcJ

Reference opening time to local time on each day of the year, and then refer that back to UTC.

Like California is -8 in Standard, -7 in Daylight, so a 9:30 AM opening in the Winter is at 17:30 UTC, in the Summer, 16:30 UTC.

It's a hassle but programmers are supposed to model reality.

As an example of the problems that can arise, I remember when the new Japanese Emperor was to take office upon his father's abdication, there was a big fuss because the Era Name was customarily only revealed after the new Emperor's reign started but all the computer people wanted to be ready in advance. Not sure what finally happened, if it was revealed in advance or not.

tsimionescu

What if the date for DST changes tomorrow, but only in some locations? How will you know which stores times need to be adjusted and which don't?

UTC to local time is not a function, it is not somethung that can be computed once and stored for the future. The two are fundamentally different concepts, and can only be related to one another in certain contexts, and only reliably for the past.

pelorat

you don't, since they are different times?

undefined

[deleted]

konschubert

store_opening_hour_and_minute_of_day=(9,0)

It’s not a date time.

BugsJustFindMe

I don't understand why the functions weren't just made to return non-naive results. You've literally asked for UTC. There's no excuse for allowing the result of that to be interpreted as something that isn't UTC.

Set a separate flag that governs conversion to string to avoid different ISO output for shitty string parsers if you want, but there's no great reason to not just fix the functions so that they continue to work better than before and do the thing that people actually expect them to do, which is produce UTC.

Intentionally naive storage or transfer is irrelevant. That's just serialization. And when you explicitly tell the computer to "deserialize this as UTC" it should fucking do what you told it to and give a zone aware result.

drkevorkian

This would be a backwards incompatible change that would cause a lot of issues. For instance, you are not allowed to compare naive and non-naive datetimes, so for instance, `utcnow() > datetime(2023, 11, 19)` would work before, but break following your change.

akersten

Removing the functions wholesale isn't a backwards incompatible change?

ollien

It is one that can be found via static analysis. That may not be true if behavior is changed. In some cases, this may be "ok" (see: Go's recent loop changes), but in others, it may not.

ak217

Breaking following the change is fine. Silently changing the behavior in a way that could cause catastrophic bugs is not.

That's why the suggestion to just keep the functions and change their behavior is naive. It would obviously be very unsafe to do so.

BugsJustFindMe

That's going to break following this change anyway.

sanderjd

But in a much more obvious way. Noisy errors are better than quiet inaccuracy.

They screwed up these methods from the start, and removing them is the only way to get rid of the confusion, without introducing subtle breakage.

ak217

Let's imagine that I have a perfectly reasonable looking piece of code in my app:

    db.write(Event(timestamp=int(datetime.datetime.utcnow().timestamp()))
After the change that you propose, the timestamps written by this code will jump by an amount equal to the offset of the local timezone this machine runs on (and also lose any DST adjustment they might have had).

Now, let's imagine another independent process is consuming events from the database and compares an event written before this change to one written after.

Python is a popular language, used in production by scheduling applications around the world. The potential downside of this kind of change is measured in billions of dollars. The safe solution is of course to not silently change the API in a breaking way, and instead introduce a new API and get someone to look at why the code stopped working.

wodenokoto

On my machine, a naive timestamp from utcnow() and a utc timezone aware datetime object from datetime.now(tz=ZoneInfo('utc')) produces the same timestamp.

datetime.now() does not return utc time (but does return a naive datetime object)

ak217

OK, but that's not relevant to the scenario that I described.

thrdbndndn

> I don't understand why the functions weren't just made to return non-naive results. You've literally asked for UTC.

I totally agree with you that it makes no sense this `utcnow()` does not return tz-aware object.

But I think their fix is great in this regard: now you just use `datetime.now(timezone.utc)`. It's more explicit, it returns aware DT object now, and more importantly, it gets rid of a function that I always feel too specific to have anyway (like how we don't have `plus(a, 2)` and `plustwo(a)`).

sanderjd

Except isn't datetime.now() still going to return a tz-naive datetime? I would much rather have a method that requires an explicit tz, or explicitly uses UTC (like utcnow, but with the right return type).

Looking for this mistake in code reviews gets really old.

abh123

I got bit by this once. Timezones aware date calculations can be an order of magnitude slower than non tz aware. Consider every time a legislative body changes dst, it creates an entry in the timezone database that needs to be checked when adding or subtracting time from that timezone.

ryukoposting

This is one of the reasons why Unix epoch time soldiers on, even though it is totally indecipherable to humans. It can be easily mapped to a timezone-aware type, but performing arithmetic on it is trivial.

InitialBP

If this was something used only by your company or a specific project, then I’m absolutely on board. However, this is in a library used in thousands (millions?) of projects. Since it’s potentially a breaking change you can’t just change it and expect everyone to know.

Many people won’t know it’s deprecated until the code fails to run, and having new functions rather than changing the functionality of existing functions makes it much easier to identify what is actually happening.

ak217

Code failing to run is the good outcome.

raverbashing

For real, as much as I'm annoyed with the change, this is how it should have been

It is kinda like the 2->3 change with strings

And utcnow is a bad name. But the "fix" is none the better

sillysaurusx

One advantage of getting older is that you see a lot of change. In the long run, simple ideas tend to win. And there have been lots of cases where the programming world collectively agreed that some more complex idea was the right way, then a decade later everyone has reverted to the simple idea.

UTC is simple and unambiguous. Time is a number representing a fixed point in time. When displaying it for humans, convert it into human form. When this principle is applied everywhere, it’s hard to make mistakes.

My gut says that deprecating utc as the native time representation will be one of those ideas fervently embraced by a few, ignored by most, and then quietly forgotten about in a decade.

ryandrake

It doesn't seem like they're deprecating "utc as the native time representation." They're just making it harder to get a datetime object that "has no time zone." The message with this change is: Go ahead and keep using UTC, but explicitly specify it, and the object itself will know it's own UTC-ness.

Spivak

This misses what the change actually is. Python has two datetimes, one which includes the timezone info and one which doesn't (naive).

There is no assumed timezone for naive datetimes and different software treats it differently. What's being deprecated is methods to create naive datetimes that are implicitly UTC without just attaching that information to the object itself. In the new world everything is still in UTC and you convert to local time at the last minute but now you can be sure that the datetime object you got handed is actually UTC instead of it being a convention that isn't always honored.

p5a0u9l

They’re not deprecating UTC. Did you read the link? They’re deprecating functions that read as authoritative, but are actually naive about timezones, which can less to non-UTC results.

sillysaurusx

If that were true, the recommended fix would be to continue using utc (as numbers). Instead, the recommendation is to use datetime objects.

This, I think, is the idea that will be quietly ignored in the long run.

sanderjd

I think the recommendation is to use a datetime with the timezone explicitly set to utc? I think the numbers vs. objects thing seems like a distraction...

im3w1l

It's hard not to draw the parallel to encodings. Implicit whatever -> Explicit whatever -> Explicit utf8 -> Implicit utf8

remram

What is "utc as numbers"?

worik

> "naive about timezones"

That is what they said, but it is inaccurate

All time should be UTC until it is displayed

So a number without a timezone is seconds since epoch in UTC

That is "default" not naive

Some Python applications programmers made stupid mistakes so they change the library

Golly. On the face of it Python is a mess. And it is everywhere. Golly

int_19h

You're focusing on representation where you should be thinking about semantics.

A "naive" datetime is the one for which it is not known what the timezone is. The opposite is the one for which it is known. You can absolutely encode UTC timezones as seconds since epoch without any additional information (except that one bit that is needed to distinguish them from "naive" ones, which doesn't have to be a literal bit - it can be just a different data type, for example).

And, yes, it would sure be nice if we didn't have "naive" datetimes at all, and everything was always UTC. But there are too many datetimes recorded in the real world without enough information to recover the timezone and thus the precise UTC time, and they still need to be processed. The mistake was to make this the default behavior - but that is a very old one, dating back to earliest days of computing.

happytoexplain

Time is two different things. Just making everything UTC until display time is incompatible with that. Sometimes you need to operate on calendar units or clock units as part of business logic.

worik

> Sometimes you need to operate on calendar units or clock units as part of business logic.

And you must do it in UTC

erik_seaberg

To make something happen at 9 AM every day in the user’s time zone, choosing UTC will make it harder.

globular-toast

All of this is fine if you are talking about timestamps. But Python's datetime library can do more than that. Basically once you get into future dates that it all starts to fall apart.

gizmo

Good point. Also, as long as javascript will happily convert an integer into a new Date() people will want obvious compatibility in Python.

oblvious-earth

Discussion on Python discuss: https://discuss.python.org/t/deprecating-utcnow-and-utcfromt...

I'm the one arguing against this move, I've already made my thoughts clear that it's a lot of churn, e.g. the PR to remove it from Pip literally caused Pip to have to do a bug release, and has valid use cases, e.g. modelling datetime data types from spreadsheets and databases that do not have timezones.

But I also accept I'm not the one maintaining Python, so I've updated my codebase appropriately (`datetime.datetime.now(datetime.UTC).replace(tzinfo=None)`). Python is not a backwards compatability language, and it's clearly not a strong motivation for most users as I don't see anyone attempting to write a backwards compatibility shim over the standard library, so no point complaining too much.

m12k

Time handling seems like one of those cases where a type system could really come to the rescue - times with and without time zones in them shouldn't be the same type, and using one in a place where the other is expected should ideally just give you a compile error.

frou_dh

Reminds me of trying Scala and a library where not only were paths a type rather than primitive strings (good, like pathlib in Python), but absolute and relative paths were actually different types.

I think this was it: https://github.com/com-lihaoyi/os-lib

vore

Timezoneless time I think is just a mistake in general – all times inherently have some timezone, even if the timezone is UTC.

garblegarble

Here are two counter examples that sprang to mind:

1. I've set my alarm for 8am local time every day. I don't want my alarm clock to go off at 3am just because I'm in a different country

2. If I have an appointment at 10am next November, that's actually a datetime with a locale (given that my appointment is at 10am local time, no matter whether the DST rules change between now and then).

marcosdumay

Well, you'll need another type meaning "local time" for #1. That's not a time without time zone, it's an entirely different thing.

Most environments simply can't represent that thing. They never could. With those changes this becomes more obvious, and with some luck people will finally fix this.

(The most absurd case is the "timestamp with local time zone" from SQL, that reads exactly like what you want, but represents a timestamp in a specific time zone, that is discoverable but mostly unknown.)

eieio

At my last job we had types for a `Time.t` (time + date + timezone), a `Date.t` (just a day of the year), and a `Time.Ofday.t` (a time of the day with no timezone or date attached - like 8:00 AM).

This worked really well! You represent (1) with a `Time.Ofday.t`. I suppose if you wanted you could represent (2) with a `Time.Ofday.t` + a `Date.t`, although it kinda seems to me like you want to keep timezone information around if you're dealing with DST changes.

magicalhippo

I think ISO 8601 made a big mistake by allowing timezone-less representation[1]. They should have used L for local time so it's explicit, and not allowed any timezone-less representation.

Sure it's technically well-defined as it is, but I think it's too important not to be written out.

In that case you can represent your alarm either as 08:00L if you want to wake up in the morning regardless of where you travel, or 08:00-02 for those cases where you need to stay in sync with home say.

[1]: https://en.wikipedia.org/wiki/ISO_8601#Local_time_(unqualifi...

wayfinder

1. That isn’t date data. That’s just storing a local time.

2. That’s why you WANT time zones in this example. It will automatically stay at 10am instead of bouncing around when DST rules change.

I’ve never ever needed timezone-less dates. Even using UTC or timestamps, it’s still UTC.

A date without a time zone is like “10 inches” but without the inches so it’s just “10”. Absolutely meaningless. You start moving just “10” around without the units in your code and then your Mars Orbiter explodes.

magnio

> 1. I've set my alarm for 8am local time every day. I don't want my alarm clock to go off at 3am just because I'm in a different country

Without timezone, your clock would actually go off in the middle of the night when you are in a different country. Your clock does not know you change location (no timezone, no location-dependent time), so it will alarm you after exactly 24 hours since the last alarm, which, in another country, can be midnight.

> 2. If I have an appointment at 10am next November, that's actually a datetime with a locale (given that my appointment is at 10am local time, no matter whether the DST rules change between now and then).

If everyone is staying in your city, then that works great (sans catastrophic continental riff or meteorite strike). When at any point you involve more than one geographic location, then the appointment is meaningless without timezones.

Now, maybe it is actually the case that you and your software only care about one geographic location in perpetuity, but just like assuming 32-bit IP addresses, 8-bit ASCII, and length-oblivious arrays are all you need, the teeth marks from its consequential bite tend to be quite deep and sanguine.

asddubs

1 could be better served by an integer representing the minute it should go off anyway, since there is no specific date attached

2 time zones account for DST so that point is moot, but in the context of traveling and still wanting to maintain the same times this is actually something calendar apps often get wrong

jes5199

OK, you’ve convinced me that having a naive datetime object available makes sense

but are there any cases where “now” being naive is useful

notatoad

datetime with locale is how timezones are represented in python. What you're asking for there is a datetime with a timezone, not a datetime without a timezone.

gcbirzan

They don't, not always. I want to wake up at 7am every morning, regardless of where I am.

vore

That's true!

happytoexplain

"8am" is a time that inherently has no timezone, and yet we need it. It's not that we don't need timezoneless time - we just need to stop using timezoneless time to represent times with a time zone and vice versa. Most time APIs were simply designed wrong on purpose for "simplicity".

IggleSniggle

All timestamps even have a position in space that will experience discrepancies relative to all other timestamps, even if they are UTC, we just usually don't care about it that much.

Since our time is at least all Earth-based, we could do even better than timezone and make timestamps have a lat/long attached for the place in which it was produced. Maybe a linked list for any timestamps that are calculated from that based type.

Are we having fun yet?

vore

The social solution is to abolish timezones (mine is of course objectively the right one, other people must deal with breakfast at 9pm wherever they are).

0cf8612b2e1e

I need a null value for when the timezone is unknown. If a user enters 9:30, they do not want to be bothered with specifying a timezone if they keep everything local to their life.

WirelessGigabit

I disagree.

If we have a call at 9:30 and you drive to the next state now that call is at 10:30 or 8:30 for you.

If you set 9:30 as an alarm to feed your cat every day, fine.

rileymat2

If that is the case, can't the UI encode the timezone for the user, whether they want to be bothered or not?

ndriscoll

When is Christmas?

bobbylarrybobby

But UTC “times” aren't times at all. They're durations (since midnight Jan 1, 1970 in Greenwich), so they don't need a time zone.

Hamuko

Are you thinking of Unix time?

SpaghettiCthulu

Well then maybe they should store the epoch alongside the duration value too! Wouldn't want to get confused thinking it was duration since some other epoch!

MaulingMonkey

Rust's `time` crate does have separate types for these:

    https://docs.rs/time/latest/time/struct.OffsetDateTime.html
    https://docs.rs/time/latest/time/struct.PrimitiveDateTime.html
It's not as helpful as you'd think IME - timezoneless date times are suprisingly niche (at least as a useful tool to intentionally choose, rather than an accidental side effect of API choice.)

jepler

It's funny you should say this.

Reading this article prompted me to future-proof a program I maintain for fun that deals with time; it had one use of utcnow, which I fixed.

And then I tripped over a runtime type problem in an unrelated area of the code, despite the code being green under "mypy --strict". (and "100% coverage" from tests, except this particular exception only occured in a "# pragma: no-cover" codepath so it wasn't actually covered)

It turns out that because of some core decisions about how datetime objects work, `datetime.date.today() < datetime.datetime.now()` type-checks but gives a TypeError at runtime. Oops. (cause discussed at length in https://github.com/python/mypy/issues/9015 but without action for 3 years)

One solution is apparently to use `datetype` for type annotations (while continuing to use `datetime` objects at runtime): https://github.com/glyph/DateType

usrusr

The way you put it makes it appear very surprising that time is not the extended hello world of type systems. Maybe it's because no environment has ever arrived at an implementation they are actually happy with, before fizzing out at "good enough"? It's clearly a topic where we tend to prefer something rough but shared over something better but custom, so the "good enough" is powerful.

physicles

This would be fantastic. As someone who just occasionally touches Python, I can’t count the number of times I’ve been bitten by bugs caused by unwittingly mixing tz-naive and aware datetimes.

amelius

The whole concept is broken anyway, if you look at relativistic scales. Good luck running Python code inside a GPS receiver.

Dylan16807

Don't the satellites themselves compensate for relativity?

kstenerud

I look at the arguments in this post and see echoes of Y2K:

- It's a clever hack based on an assumption that dismisses the fact that this assumption can change (that the time zone will never be changed, or that everyone will follow the same rules once it does).

- The argument for doing it is: It "uses less space" and "takes less time"

These are similar to the reasons why we used 2-digit years for so long.

Timestamps without time zone data are BUGS (and I mean REAL time zones, not time offsets like CET and PST). They are landmines just waiting to go off once the assumptions they're based upon change. They require your host system to be configured just-so, making your software brittle. They push the ugly details of handling many time issues that could be handled centrally into the user-space (and even worse, they make it OPTIONAL). The Python maintainers are right to remove this, and really they should have removed naive datetime when they released Python 3.

Time is one of the most notoriously difficult things to get right. I've yet to see software using time calculations (or anything more complex than recording timestamps of past events - the only thing for which UTC is useful) that is bug-free.

Time data ALWAYS REQUIRES time zone data. The only "exception" is timestamps of past events, but only because we always assume them to be UTC (and so there's an implied time zone so long as nobody bucks the trend).

globular-toast

Not quite.

Local time is very important. "Tomorrow at 9:00" is a meaningful local time for everyone, but doesn't refer to the same global time. It would be wrong to attach a time zone to such data.

Past events, on the other hand, do require timezone data if they are recording human activity, which is basically everything. "Just use UTC" is data loss. You now don't know whether at event took place at midday or midnight. Two very different results for many activities.

kstenerud

"Local time" is time zone metadata. I've written a fair bit about timekeeping, because the context of what you're capturing becomes very important: https://github.com/kstenerud/concise-encoding/blob/master/ce...

globular-toast

Imagine you have users all around the world and you've got logs of their activities. Someone asks "do users spend more time on X in the morning or afternoon"? If you only recorded absolute times and threw away their local time then you can't answer that question.

It doesn't matter whether you record UTC or local time as long as you record their time zone, you can always derive one from the other. This is an implementation detail that should be abstracted by any decent time library.

neillyons

Python should use different types to represent datetimes with a timezone and those without.

    class Datetime:
        pass

    class NaiveDatetime:
        pass
That way you can annotate functions properly.

    def timezone(datetime: Datetime) -> ...:
This is how Elixir does it. So much easier to understand as a newcomer.

https://hexdocs.pm/elixir/DateTime.html https://hexdocs.pm/elixir/NaiveDateTime.html

llbeansandrice

This seems like the blatantly obvious path to me. Perhaps that needs to be dealt with in a major version release tho. TZ naive and TZ datetimes are needed and it’s important to chose the correct one.

dikei

So is Java with `LocalDateTime` and `ZonedDateTime`, a very useful example of making your typesystem work for you.

talboren

Paul Ganssle released a great article[1] explaining why you shouldn't use utcnow in 2019.

[1] https://blog.ganssle.io/articles/2019/11/utcnow.html

ryandrake

I'm not a Python guy so am not familiar with the culture, but I'd assume many, many programs use the deprecated function, given that it made "the news." It seems not right for backward compatibility to deprecate something many developers are using, simply because the old one wasn't thought out very well, and "developers should switch" to the explicit functions. Especially since, as the author demonstrates, the deprecated one can be easily re-implemented. It seems like a developer inconvenience was added without changing the state of the world. Things like this--I don't know--make me take a development environment less seriously.

In C, we all know we shouldn't use things like strcpy() and gets(), and you'd be a total fool to add them to new code. But for the sake of backward compatibility with programs that aren't going to change, they should be kept in and documentation should nudge people to do it the right way. Maybe that's the Python way of nudging: "This function is deprecated!"

jkrejcha

Fwiw, gets() was actually removed in C11 because of it's inherit security problems. :)

But aside from that, I think it's just a different style. Waiting 10 years from deprecation to remove a deprecated thing might be required with C just because of how prevalent C is and how much the developers in that have to think about basically every platform, but removing something on a major release isn't inherently bad, it's just a different tradeoff (being able to move a bit faster and fix some design issues vs. being very very good at backwards compat)

The deprecated function can obviously be reimplemented pretty easily, but so can gets(). With utcnow(), it had some unfortunate effects in that it didn't really do what people thought it did, and because of that, most of the uses were basically bugs to begin with.

(Having experience with .NET for example, you'd think that DateTimeOffset.UtcNow and datetime.utcnow() are semantically similar, but the problem is that utcnow() doesn't actually have a timezone attached to it. Adding one would also be a breaking change, and one that is more subtle.)

akira2501

> Fwiw, gets() was actually removed in C11 because of it's inherit security problems. :)

It always exists, it's just that the import gets controlled by a macro. Which, hints at a way Python could have solved this same problem without requiring auditing and rewriting code.

int_19h

Different language ecosystems have different standards for backwards compatibility, with C (and e.g. Java) being incredibly conservative by modern standards. This is not a good or a bad thing per se, it's just something to consider when picking a tool for the task at hand.

blincoln

Am I correct that the datetime.datetime.now(datetime.timezone.utc) syntax is backwards-compatible all the way to Python 3.2?[1] If so, this seems like a good move. The edge cases like compatibility with data sources that don't indicate the time zone seem like less of an issue than data corruption due to developers not realizing that they were working with "UTC" timestamps that weren't actually UTC.

I'd be more concerned if this was one of those changes where there isn't a good way to write reasonably straightforward code that will run in relatively old versions of Python as well as newer ones.

[1] https://peps.python.org/pep-0615/

Belphemur

They should have gone further like .NET 8.0 with a full class abstraction for datetime provider: https://learn.microsoft.com/en-us/dotnet/core/whats-new/dotn...

This is 10x better and helps to assure the code can be unit tested with providing the exact date we want in the exact format/timezone

lallysingh

That's a lot of complexity. How's that better than requiring an arg with the timezone?

rjbwork

Because you can now fully simulate arbitrary times during testing by providing your own implementation of the time provider. If you just take in a timezone as an argument, how will you simulate it being 2041-08-23T21:17:05.023743Z?

SpaghettiCthulu

Uh, just assign your mock function to `<insert name here>`? Python is really the wrong language to be complaining about a lack of mockability.

Daily Digest email

Get the top HN stories in your inbox every day.

datetime.utcnow() is now deprecated - Hacker News