datetime.date objects have a fromtimestamp method, but they do not have a .timestamp() method, as datetime.datetime objects have. That seems inconsistent to me.
Just as the .fromtimestamp() method truncates the time information given by the timestamp (Unix time), a .timestamp() method would have to implicitly use a time - e.g. 0 hours in the local time zone (as date objects are naive). As a work-around, you can create a datetime object from it by using combine:
from datetime import date, datetime
d = date(2020, 1, 1) # on UTC+1
dt = datetime(2020, 1, 1) # for comparison
print(dt.timestamp())
# 1577833200.0
print(datetime.combine(d, datetime.min.time()).timestamp())
# 1577833200.0
But why not add this method to the datetime.date class?
The short answer is that dates do not have second precision - theyâre
entirely to do with whole days. As you demonstrate you can make a
datetime with just a year/month/day supplied, so if you want seconds
precision, just do that.
The other answer is that the datetime module has a lot of rough edges.
There are various third party modules which build on it to provide
better or more complete interfaces. I recommend you try one of these.
Also, all your things above assume a timezone (which is not simply a
GMT/UTC offset). Always tricky. This ambiguity is one of the reasons
people might be loathe to pretend seconds precision when all you have is
a day.
I know about the ârough edgesâ and that there are alternatives. But I was surprised by the inconsistency - for example thereâs also a timetuple method, which returns an object that represents date/time in a higher resolution than âdayâ! - hence the idea. Not sure if this is really useful for everybody in practice - hence the question here Thanks for your comment!
The timetuple() method returns a time.struct_time, which directly
mirrors the C âstruct tmâ returned by the POSIX gmtime() and localtime()
functions. This is why it exists.
Why we are on this topic, why doesnât python have date.strptime(), and if one wish to convert string to date, one have to use datetime.data.strptime().date().
My point in general is: if the Python standard library provides a date class, it should be full-featured. Other libraries (e.g. numpy, and built on that: pandas) only have a datetime type; if you want only the date, youâll have to floor/normalize the hour, minute, etc.
My point in general is: if the Python standard library provides a date class, it should be full-featured.
For the record, I donât actually disagree with this as a design
principle or objective. But it can be a fair bit of work, and some
things such as date.timestamp() => seconds require a bunch of clarifying
assumptions like âfloor/normalize_
the hour, minute, etcâ mentioned below and also the timezone. These
complicate the expected semantics.
Other libraries (e.g. numpy, and built on that: pandas) only have a
datetime type; if you want only the date, youâll have to
floor/normalize the hour, minute, etc.
This I think is the saner way to go. Just work with datetime throughout
when possible. At least it halves the API space and also youâre now
working with a thing which inherently has seconds precision.
Personally, I work with unixtimes throughout (seconds since the UNIX
epoch) if I can, and ony use datetimes etc for presentation. Not always
feasible, but more reliable because the times are at least not ambiguous
(no timezone weirdness, not repeated or missing times due to
summer/winter timezone offset shifts, no utterly weird arithmetic behind
the scenes because of the objectâs value is effectively expressed as a
sum of rational numbers whose demoninators vary (looking at you,
days-in-a-month and days-in-a-year)).
There is a lot of domains where date is the only thing that needed. So carrying seconds with it is not only unnecessary, but potentially problematic (e.g. I write my code with datetime assuming all time is â12:00:00â, so I can write date1 == date2 for comparing dates, but then one second is added somewhere and my code stop working).
And datetime.date is already fully functional, with just a few things missing (absence of strptime is what bothers me the most)
Having said that, the closes analogy I see is unicode and non-unicode strings, where multiple domains use strings but just dont care about unicode characters at all. And Python handles this issue by dropping the non-unicode stringâŚ
If you feel its important to add, you could open an issue on BPO to discuss it, and if thereâs general agreement that it would be a net improvement, you could submit a PR. It should be quite doable if you have a decent level of Python experience (unless it also needs to be implemented as a C extension, in which case you would need to have some basic C experience tooâcanât remember if it is).
There is a lot of domains where date is the only thing that needed. So carrying seconds with it is not only unnecessary, but potentially problematic (e.g. I write my code with datetime assuming all time is â12:00:00â, so I can write date1 == date2 for comparing dates, but then one second is added somewhere and my code stop working).
Doesnât this situation inherently display the trickiness of assuming you
can get a seconds timestamp from a date? The relationship seems very
fragile.
That said, I agree that if youâre working only with dates, use âdateâ.
Then there are no additional ill specified hours etc fields to break
your comparisons. But going with that, I would not expect to extract a
seconds precision value.
And datetime.date is already fully functional, with just a few things missing (absence of strptime is what bothers me the most)
Yes, strptime would be good. It might merely be missing (nobody
bothered) or the datetime.strptime might call the C/POSIX strptime
directly using a struct tm or similar, and to do that you need to invent
the missing fields (even if simply all zeroes).
If that is the case I would be inclined to argue that date should npt
have a strptime method, and that the required conversion to datetime
should be overt to make it clear what assumptions about hours, timezones
etc were involved in that conversion.
Having said that, the closes analogy I see is unicode and non-unicode strings, where multiple domains use strings but just dont care about unicode characters at all. And Python handles this issue by dropping the non-unicode stringâŚ
Thatâs an unfair comparison.
There arenât âUnicode charactersâ as such - it is meant to cover all
existing human character sets. (I guess some new things like emojis
might be defined only in Unicode, so they probably count as âUnicode
charactersâ.)
What Python did was drop support for the old 8-bit str type, which was
(a) too small for anything but parochial text and (b) had no
association with a character set - it was just bytes underneath and if
they didnât match up with your external character mapping they were just
nonsense.
Storing all text as Unicode means you can store any text, and the
transcription into files or onto displays like terminals or web pages
involves specifying the encoding of the characters, making overt what is
going on. Likewise the reverse: you canât get a Unicode string from some
bytes without specifying what encoding the bytes use.
This is analogous to making a datetime from a date - you need to define
the conversion (eg how the new hh/mm/ss and timezone are generated). You
can punt on the timezone with datetime, getting a ânaiveâ datetime. But
the object inherently has a timezone field, even when the field says
âunspecifiedâ.
Just to clarify one point, it didnât drop it at all; it was just renamed bytes and the semantics were changed to no longer implicitly and silently treat it like a string of of ASCII/Latin-1 characters when it was really a sequence of arbitrary 8-bit binary bytes, which ends up being a major footgun for those who assumed it was the former.
FWIW: I also would find useful to have a way to directly retrieve the timestamp from the date object, without the need to pass to an intermediate datetime
In my case Iâm building a simple 2d diagram (value over months) and, while in my internal data the dates are actually datetime.dates (I donât have / need bigger precision) the GUIs expect floats.
One reason this doesnât exist is in your statement above: âI_
donât have / need bigger precisionâ. The word âprecisionâ means that you donât know a seconds level resolution for the date. Any conversion to
seconds inherently involves an assumption about the start time in
seconds of a given date, and that depends on a timezone. It also assumes
a starting point for a day. usually that is midnight, but I can imagine
domains where midday might be what the âdateâ idea refers to.
Also, what happens if your dates cross a summer/winter time adjustment?
Are they local time? Should they⌠step?
So youâre always going to be performing some conversion with some outer
context not part of the date. This is why thereâs no presupplied thing -
there are a few things it could mean, and it is probably best for those
things to be explicit in some conversion function you yourself supply.
Indeed, if youâve only go âdayâ precision, do you really know precisely when the data values apply?
I think Iâm saying youâre doing presentation (i.e. providing some GUI
ordinates in seconds) and youâll have to specify it somehow. Put it in a
function with an explainatory docstring and proceed:
Itâs not that I donât know. Itâs that I donât care.
For simplicity I could assume the âtimestampâ of a date is equal to the timestamp of a datetime with the same date and â00:00:00â as time, but thatâs it. I donât really care if todayâs timestamp is exaclty 1679987083.11146, for me itâs just enough to return 1679954400.0
date objects are naive ones. There is no timezone attached to them. They are local by defintion.
Yes. That data values applied to that day. I choose this level of precision. Itâs what I need in my case.
Otherwise⌠do you really know, with femptoseconds precision, when the data values apply?
specifically for my GUI I have a chart where the x-coordinates are years, and I have roghly speaking, a day thas is âlargeâ as a pair of pixels.
Itâs just that the library Iâm using, internally, expect the values as floats.
Yeah, I can easily implement my date_for_gui, Iâve already done it. The fact is that my_date.timestamp() is really just something that makes sense to me.
Itâs not that I donât know. Itâs that I donât care.
Thatâs fine! You should still document that in the docstring of the
conversion function you end up using.
For simplicity I could assume the âtimestampâ of a date is equal to the timestamp of a datetime with the same date and â00:00:00â as time, but thatâs it. I donât really care if todayâs timestamp is exaclty 1679987083.11146, for me itâs just enough to return 1679954400.0
Ok, but therâe s an assumed timezone not mentioned above. Sounds like
UTC would suffice though, to make things easy.
date objects are naive ones. There is no timezone attached to them. They are local by defintion.
date objects are indeed naive. That doesnât mean theyâre local time.
It means they have no timezone information associated with them at all.
It sounds like you could treat them as localtime and get working
ordinates for your plotting. Not that they are inherently localtime.
Yes. That data values applied to that day. I choose this level of precision. Itâs what I need in my case.
Thatâs fine.
Otherwise⌠do you really know, with femptoseconds precision, when the data values apply?
Of course not. But what Iâm getting at, which I think you entirely
understand anyway, is that going to seconds implies some kind of
increase in precision unless youâre carrying around some additional
error bars or something.
Iâm sure we all have the experience of seeing some foreign news report
which says something like â10am on Tuesdayâ and absent details, playing
guessing games about what that actually meaning in the local calendar. I
have it all the time here (GMT+11) versus USian news reports (GMT-n) for
various small values of n.
The date isnât inhenerently localtime, and for such a news report I know itâs not my local time. It is a date lacking timezone
information.
specifically for my GUI I have a chart where the x-coordinates are years, and I have roghly speaking, a day thas is âlargeâ as a pair of pixels.
Itâs just that the library Iâm using, internally, expect the values as
floats.
Yeah, I can easily implement my date_for_gui, Iâve already done it.
The fact is that my_date.timestamp() is really just something that
makes sense to me.
It doesnât to me unless it has a bunch of parameters, or documentation
saying that certain potentially parameterisable things are in fact
assumed to have some particular values.
[Rummages.] Look, hereâs a tacky and long obsolete function I used to
use sometimes:
def localdate2unixtime(d):
''' Convert a localtime `date` into a UNIX timestamp.
'''
return mktime(date(d.year, d.month, d.day).timetuple())
That does indeed use my localtime as an assumption, but at least itâs
written in the docstring. (Iâm not recommending this particular function
to you at all.)
I honestly thing that out in the wild there be a lot of projects with very similar one-liner functions that convert a date to a timestamp apart yours and mine
and this IMHO add to the reasons to add to the stdlib
for very obvious reason the function should be documented and with a specific behavior, but in my mind itâs perfectly reasonable to offer a semantic that
assume that the date is in local time
return the timestamp at 00:00 in that day
FWIW yeah, naive == local is an assumption, but honestly, I donât really think Iâll ever use plain dates when there are timezones involved (like a date and an external tz string⌠is calling for troubles)
The trouble is, thatâs not the ONLY reasonable semantic. If you asked me, I would have assumed that the date was in UTC, not local time. And while neither of those is inherently wrong, they are incompatible in ways that probably only half the world will find issue with (depending on which direction itâs wrong; if you ask for a date and it gives you the timestamp for 4AM that day, itâs probably fine, but if you get the timestamp for 8PM the previous day, thatâs not fine, and the difference between those depends on whether youâre east or west of Greenwich and which way around the thing was written).
So thatâs a reason to NOT add it to the stdlib. A naive date object simply doesnât have enough information to give a timestamp, and whatever you pick will be wrong for some people. My recommendation? Explicitly make a datetime out of it first. You can then attach whatever timezone information you like (including ânaiveâ or âlocalâ, which arenât timezones but same difference), and itâs documented within your code.