Closed pithu closed 5 years ago
Instant
is a moment in time without any notion of timezones. ZonedInstant
is an Instant
with a timezone.
From a ZonedInstant
you can then get a GregorianDateTime
, GregorianDate
or GregorianTime
. Or in future a HebrewDateTime
or an EthiopianTime
or a CopticTime
or a JulianDate
or ...
Just as a thought, ZonedDateTime
in JSR-310 entirely ignores different calendars. So it's actually not a good solution. I think our current split is much better than JSR-310.
An Instant
is a point in the timeline at UTC
, so a ZonedInstant
at UTC is the equal to an Instant
, therefore having an extra domain Instant
together with a ZonedInstant
is somehow redundant or superfluous.
I don't see your point that is better suited to define different calendar systems. A ZonedInstant
and a ZonedDateTime
both express a point in the timeline and you can convert on into the other.
But the main difference is that ZonedDateTime
is much better suited to give, me as a developer a domain language to describe my real world, day to day issue. Its start from a Local/ Civil/ Simple/ however DateTime and adds whats missing there, the timezone and the offset to UTC.
Instant is defined as the number of periods of radiation of the cesium133 atom since a specific point in time measured in units of “9,192,631,770 periods of radiation” or si-fractions thereof.
There is no timezone involved.
ZonedInstant takes such an Instant and places it within a timezone.
The ISO/Gregorian object allow that instant to be represented in accordance with a specific calendar/time representation.
In other words none of them are superfluous; They each have distinct meaning and use.
The reason I like ISO as a prefix, is because the calendar/time representation used is that of the ISO-8601 standard (i.e. proleptic Gregorian calendar i. combination with 24hr midnight based days).
Other calendar systems are:
Ethiopian: proleptic Gregorian calendar with 12h 6am-6pm-6am days
Hebrew, Coptic, Chinese, ...
Which will be represented in distinct objects that work in cooperation with ZonedInstant.
These calendar/time systems have no notion of timezones in themselves. They are always localtime. So they need to work with a ZonedInstant.
I hope that clears up the distictions.
On 23 Sep 2018, at 11:15, Philipp Thuerwaechter notifications@github.com wrote:
An Instant is a point in the timeline at UTC, so a ZonedInstant at UTC is the equal to an Instant, therefore having an extra domain Instant together with a ZonedInstant is somehow redundant or superfluous.
I don't see your point that is better suited to define different calendar systems. A ZonedInstant and a ZonedDateTime both express a point in the timeline and you can convert on into the other.
But the main difference is that ZonedDateTime is much better suited to give, me as a developer a domain language to describe my real world, day to day issue. Its start from a Local/ Civil/ Simple/ however DateTime and adds whats missing there, the timezone and the offset to UTC.
— You are receiving this because you commented. Reply to this email directly, view it on GitHub, or mute the thread.
What you saying about Instant confuse me, i have no idea what you talking about and its not fitting to the docu here.
@pithu sorry for having been unclear. I was trying to explain the conceptual distinctions.
“9,192,631,770 periods of radiation”
is the official definition of a second
. The reason I chose that for of expression was to make it distinct. Obviously I failed in clarifying the distinctness of the concepts.
I wanted to clear up that Instant
is meant to be a simple measurement type. One from which no direct corollary to a specific Date/Time is to be drawn. Once one realises that it's just seconds since a specific point in time, I thought it become clearer that an Instant
is not really meant as a point in the UTC-timeline, but rather an abstrct way to determine a specific point in time independent of timezone.
Only once you add a timezone and make it a ZonedInstant
, do date-calculations become a thing.
I hope that's a bit clearer. If not please do nag, and I'll ty again.
@pipobscure I am also confused about Instant
definition...
Instant is defined as the number of periods of radiation of the cesium133 atom since a specific point in time measured in units of “9,192,631,770 periods of radiation” or si-fractions thereof.
There is no timezone involved.
If there's no timezone involved, what's the starting point ("since a specific point in time")? It seems to me there's a reference time and it's based on a timezone, isn't it?
An instant is a point in time independent of location. The POSIX epoch is 1970-01-01T00:00Z, which is exactly the same as e g. 1969-12-31T19:00-05:00, and other instants are defined in relation to it. Or put another way, the addition of location data doesn't change the value of an instant, it just changes the preferred representation.
Since defining an instant clearly involves stressing the zoneless nature of it, isn't ZonedInstant
a bit of a weird term to comprehend? (i.e. "A zoneless point in time, with a zone").
@gibson042 it's independent of location, but NOT of timezone, hence Z
(which means Zulu, i.e., UTC) in 1970-01-01T00:00Z. What I am insisting here is that I also agree there's a confusion differentiating Instant
from ZonedInstant
, because it seems like Instant
is just a ZonedInstant
in UTC. There's no such zoneless point in time if you think about it.
Having a separate type for Instant is critical for conveying the semantic that the time zone doesnt matter. A zoned instant in UTC does not convey that.
I dispute that a separate type is critical for conveying that semantic (as opposed to e.g. nullable time zone data on a single Instant type), but the semantic itself does seem to matter and is not captured by setting time zone to UTC.
@rxaviers Z
does not mean Zulu
! Zulu is simply the NATO alphabet way of saying Z
. It means Zero Hours
and denotes the time-offset from prime meridian.
As such it's not a time-zone. It's actually a Zero-Time-Zone of sorts.
Which incidentally is also the reason why:
const instant = new Instant(0n);
instant.toString(); // 1970-01-01T00:00:00.000000000Z
instant.withZone('UTC').toString(); // 1970-01-01T00:00:00.000000000+00:00
Thanks for the clarification. Now, I understand the theoretical difference between Z
(meaning Zero Hours
, no time zone) and UTC
(meaning +00:00
).
@gibson042, I'm taking the liberty to "move" your comment https://github.com/tc39/proposal-temporal/issues/84#issuecomment-423997000 above here: https://github.com/tc39/proposal-temporal/issues/42#issuecomment-424042545
Which incidentally is also the reason why:
const instant = new Instant(0n); instant.toString(); // 1970-01-01T00:00:00.000000000Z instant.withZone('UTC').toString(); // 1970-01-01T00:00:00.000000000+00:00
This is an extremely subtle distinction that therefore needs to be a prominent aspect of documentation and discussions around the proposal.
Z
and +00:00
mean precisely the same thing in RFC 3339, and if anything ISO 8601-1 prefers the former for UTC ("The zone designator is empty if use is made of local time in accordance with 4.2.2.2 through 4.2.2.4, it is the UTC designator [Z] if use is made of UTC of day in accordance with 4.2.4 and it is the difference-component if use is made of local time and the difference from UTC in accordance with 4.2.5.2").
Instant is defined as the number of periods of radiation of the cesium133 atom since a specific point in time measured in units of “9,192,631,770 periods of radiation” or si-fractions thereof.
I disagree. Since we are not supporting leap seconds in this API, Instant
is not a pure measure of SI seconds. It is more akin to Unix Time, in that leap seconds are treated as if they did not happen.
... an Instant is not really meant as a point in the UTC-timeline, but rather an abstrct way to determine a specific point in time independent of timezone.
Actually, it is a point on the UTC timeline. It's just that the UTC timeline also includes :60Z
values for leap seconds, and those are not represented here. Just because :60Z
second values are not represented, does not negate that other second values :00Z
through :059Z
are valid and map to their exact positions on the UTC timeline.
Z does not mean Zulu! Zulu is simply the NATO alphabet way of saying Z. It means Zero Hours and denotes the time-offset from prime meridian.
As such it's not a time-zone. It's actually a Zero-Time-Zone of sorts.
The time zone using UTC is sometimes denoted UTC±00:00 or by the letter Z—a reference to the equivalent nautical time zone (GMT), which has been denoted by a Z since about 1950. Time zones were identified by successive letters of the alphabet and the Greenwich time zone was marked by a Z as it was the point of origin. The letter also refers to the "zone description" of zero hours, which has been used since 1920 (see time zone history). Since the NATO phonetic alphabet word for Z is "Zulu", UTC is sometimes known as "Zulu time". This is especially true in aviation, where "Zulu" is the universal standard.
Z
: A suffix which, when applied to a time, denotes a UTC offset of 00:00; often spoken "Zulu" from the ICAO phonetic alphabet representation of the letter "Z".
The ISO 8601 spec refers to Z
as the "UTC Designator", and does not mention Zulu.
Thus, IMHO "Zulu" is not incorrect but we should not use it normatively. I prefer we use the term "UTC Designator" as per ISO 8601.
As to Instant
vs ZonedInstant
, indeed one could get similar results with ZonedInstant
and UTC
or +00:00
as the time zone. However, there are two key differences:
toString
and fromString
on Instant
will use Z
, while the same on ZonedInstant
will use +00:00
.Instant
values are all normalized to the same time zone, thus their values are inherently sortable, comparable, and equatable (through whatever API) without any ambiguity or further normalization.As to why ZonedInstant
rather than ZonedDateTime
, this is more subtle, but my main reasoning is that there is always an unambiguous point in time behind a ZoneDateTime
, thus it is not like the Civil types.
This is rather confusing with ZonedDateTime
in other implementations. For example, Java's says:
In terms of design, this class should be viewed primarily as the combination of a LocalDateTime and a ZoneId. The ZoneOffset is a vital, but secondary, piece of information, used to ensure that the class represents an instant, especially during a daylight savings overlap.
If it's vital, why is it secondary? If it is to "ensure that the class represents an instant", then why is it not internally using an Instant
and ZoneId
? If there's some critical advantage of using a LocalDateTime
+ ZoneOffset
internally, I don't see it.
Actually, it is a point on the UTC timeline. It's just that the UTC timeline also includes
:60Z
values for leap seconds, and those are not represented here.
That means instants are on have a fixed offset from the TAI timeline, not UTC. And the consequences are observable—e.g., 2016-12-31T23:59:59Z precedes 2017-01-01T00:00:00Z by one second in TAI but two seconds in UTC.
Except that TAI is 37 seconds ahead of UTC, and thus 2017-01-01T00:00:00Z on the UTC timeline maps to 2017-01-01T00:00:37Z on the TAI timeline. We are following the UTC timeline, despite the discontinuities created by leap seconds.
I'll point out that just about every major date/time API from any implementation in any language behaves this way, including ECMAScript's current Date
API. Very few follow TAI or track leap seconds. We are not looking to do anything different here.
Instant
values are all normalized to the same time zone, thus their values are inherently sortable, comparable, and equatable (through whatever API) without any ambiguity or further normalization.
@mj1856 please can you explain this further? It seems like the approach to compare them (Instant
and ZonedInstant
) is still undecided. In case they are compared by their instants, this statement is irrelevant, right?
@mj1856 updated for clarity. My point is that the proposal actually does not use the UTC timeline at all, but rather operates on a timeline with a constant offset from TAI (similar to GPS time and POSIX time) was wrong because I conflated the second counting of TAI with the day counting of POSIX time. But in either case, it's fine and actually important that everything works without a built-in awareness of the specific discontinuities introduced into UTC by leap seconds.
Thanks everybody. Learining a lot here. My intent was only to establish a mental model of how to think about these objects.
Let me know what the thoughts are on the following statements:
Instant
represents a specific point in time while ignoring leap-seconds. This is akin to POSIX time (which uses the same number for the second-60 as for second-59 if inserting a leap-second). This is only roughly aligned to UTC due to the earth being fairly wobly and UTC-having leap-seconds due to it using SI seconds. POSIX uses 1/86400 days as seconds instead so that leap-seconds don't occurr because seconds themselves are of indeterminate length due to the earth wobbling a bit.
The most distinguishing feature of Instant
is that like POSIX time is simply a numeric counter that counts forward at the rate of 86400 units per day (though this is done at a higher precision using metric sub-units). As such it has no inherent concept of "days", "months", "hours", etc...
It is only for serialisation/deserialisation purposes that these concepts arise and only by translating POSIX time to UTC and serializing as ISO-8601 strings and deserializing the same route back.
ZonedInstant
is our bastard child that we created because we needed an intermediary between Instant
and possible date/time representations. No-one really loves it, no-one really wants it, but where else do we put the timezone?
Instant
since that would change the fundamental character of Instant
.So we had to stuff the timezone somewhere without polluting either Instant
nor the XXXDateTime
classes so someone came up with just creating another box. I imagine the conversation like:
P1: Let's just create a separate class/box to combine an instant and a timezone then
P2: Sort of like an Instant
that has been owned ...
P1: ... or zoned more like.
P2: Eureka! we'll call it ZonedInstant
P1: Why not ZonedDateTime
?
P2: Because it doesn't have a "Date" or a "Time". Just an Instant
and a Zone.
Well that's what I'd like to imagine at least. 😄
XXXDate
, XXXTime
, XXXDateTime
are the representations of the concept of calendars and clocks (dates & times). For starters we'll only concern ourselves with what we for now call CivilDate
, CivilTime
, CivilDateTime
which employs the proleptic Gregorian calendar with 24h midnight days. In future we can create additional objects to implement other systems.
This is the first time that the concepts of days, months, years, hours, etc actually enter the conversation.
If someone could correct the likely errors in this mental model, I'd appreciate it.
The most distinguishing feature of
Instant
is that like POSIX time is simply a numeric counter that counts forward at the rate of 86400 units per day (though this is done at a higher precision using metric sub-units).
Yes, and thank you for pointing that out because I was forgetting it.
We don't want [time zone] in
Instant
since that would change the fundamental character ofInstant
.
I disagree that the fundamental character would change, and am currently in favor of allowing Instant to carry time zone information.
We don't want it int the actual Date/Time/DateTime classes, since these are independant of timezone
Right, adding time zone to the other classes would change their fundamental character.
@gibson042 how would adding a timezone not change the fundamental identity of Instant
as a monotonically increasing count of "seconds" since the POSIX-Epoch?
What I'm thinking of is more is that we may want to eliminate ZonedInstant
entirely and instead:
let xmpl = new CivilDateTime(2018, 9, 26, 13, 8);
let inst = xmpl.toInstant('America/New_York'); // 1537981740000
inst.toString(); // 2018-09-26T17:09:00.000Z
inst.toString('America/New_York'); // 2018-09-26T13:08:00.000-04:00[America/New_York]
inst.toString('UTC'); // 2018-09-26T17:09:00.000+00:00[UTC]
xmpl = CivilDateTime.fromInstant(inst, 'UTC');
xmpl.hour // 17
xmpl.minute // 8
xmpl = CivilDateTime.fromInstant(inst, 'America/New_York');
xmpl.hour // 13
xmpl.minute // 8
Is there any sincere benefit of keeping the timezone around permanently?
Just like it’s important to have the calendar be an identity you can pass around with it’s associated object, it’s important to have the time zone be preserved in the same way. Forcing it to be an independent string that i have to pass around separately doesn’t seem like a win.
@ljharb does that mean that my jovial characterisation of ZonedInstant
in my previous post is actually accurate? Yikes!!!
I wasn’t part of those deliberations, but there’s very much a use case of “i need an instant, with a zone” that necessitates it being its own object, regardless of naming.
@pipobscure,
The most distinguishing feature of
Instant
is that like POSIX time is simply a numeric counter that counts forward at the rate of 86400 units per day
Would that change for any given timezone?
No, timezone would not change the meaning at all. By that I mean that:
Then number of seconds is the same for these:
2018-09-26T13:08:00.000-04:00[America/New_York] from 1969-12-31T20:00:00.000-04:00[America/New_York]
2018-09-26T18:08:00.000+01:00[Europe/Berlin] from 1970-01-01T01:00:00.000+01:00[Europe/Berlin]
2018-09-26T17:08:00.000Z from 1970-01-01T00:00:00.000Z
So the timezone is entirely immaterial. It's just entirely irrelevant.
In my opinion it detracts the purity of Instant
a bit. It also removes the simply from that statement.
Which incidentally reminds me of a question:
What should the milliseconds
value of a ZonedInstant
be? Is it identical to that of its Instant
or is it the milliseconds since the 1st of January 1970 at 00:00:00.000 LocalTime?
Thanks...
What should the milliseconds value of a ZonedInstant be? Is it identical to that of its Instant or is it the milliseconds since the 1st of January 1970 at 00:00:00.000 LocalTime?
What would be the value of this transformation?
The meaning it adds is “where is this instant” - it adds locality.
Being on a separate object means that nothing detracts from Instant.
@rxaviers the value of that transformation would be nothing.
I am asking the question in an attempt to understand why there is this claim in some of the issues that Instant
is intrinsically sortable while ZonedInstant
is not; whether two ZonedInstant
s with the same Instant
but differing time-zones are equal;
To my simple understanding two ZonedInstant
s with the same Instant
are loose-equal, with an identical time-zone they'd be strict-equal, and sorting should sort by Instant
first offset only as a secondary characteristic.
Thanks. Yeap, we need to defined how Instant
and ZonedInstant
comparison works (cross link https://github.com/tc39/proposal-temporal/issues/42#issuecomment-424486284)
how would adding a timezone not change the fundamental identity of
Instant
as a monotonically increasing count of "seconds" since the POSIX-Epoch?
@pipobscure Because the internal time value of an Instant is preserved with or without adding a time zone annotation.
there’s very much a use case of “i need an instant, with a zone” that necessitates it being its own object, regardless of naming.
@ljharb Its own object, yes. But are you saying that the use case of “i need an instant, with a zone” would not be fulfilled by a single Instant class whose instances supported optional time zone data?
To my simple understanding two
ZonedInstant
s with the sameInstant
are loose-equal, with an identical time-zone they'd be strict-equal, and sorting should sort byInstant
first offset only as a secondary characteristic.
@pipobscure we can't achieve even Instant.fromString("1970-01-01T00:00Z") == Instant.fromString("1970-01-01T00:00Z")
with the current Abstract Equality Comparison algorithm because object-to-object comparisons end up in SameValueNonNumber, but we can achieve instant1 >= instant2 && instant1 <= instant2
.
I just argued in #68 that we definitely need something like ZonedCivilDateTime
which may eliminate the need for ZonedInstant
, having come to the conclusion (temporary though it may be) that ZonedInstant
is not the right approach. However rather than having ZonedDateTime
I'd suggest ZonedCivilDateTime
making it part of the Civil
family of objects rather than align it with Instant
.
Thoughts welcome!!!!
Added thoughts there. Thanks.
Hi @mj1856, thanks for coming back to my actual question in your comment above.
I absolutely agree that Instant
values are normalized, comparable points in the timeline and therefore the domain is a must. Introducing a ZonedInstant
has a code smell of redundancy but that is not my point.
IMO ZonedDateTime
is much better suited then ZonedInstant
to describe my day to day issues for several reasons:
ZonedDateTime
can be an ambiguous point in time. E.g. during a DST overlap, when i look at my clock, the point in time is ambiguous. With a ZonedDateTime
you can define this ambiguous point and decide what to do with it, like getting the earlier or later offset. In gap situation you can fail or jump to the next valid point. WIth a ZonedInstant
you have to decide already when converting from Local(/Simple/..)DateTime
what to do.withZoneSameInstant
, withZoneSameLocal
when converting a ZonedDateTime
from one timezone to another, making this action very clear, understandable and readable. Actually conversion between timezone is very confusing and ambiguous in most other time API's I first commented on the set of value types a long time ago. Since then there seems to be general agreement that this API can cope with about 4 main types at present. From my experience, it is pretty clear that those 4 types should be:
Instant
- an instantaneous point on the standard/UTC time-line - 2018-06-30T21:30ZLocalDate
- a date on the local time-line, aka a date without a zone - 2018-06-30LocalTime
- a time on the local time-line, aka a time without a zone - 21:30ZonedDateTime
- a date-time in a particular time-zone - 2018-06-30T21:30+02:00[Europe/Paris]Together these provide the minimal set of types necessary to do useful date-time math/work. (Any fewer, and the API would fail to meet basic needs in my view)
Instant
is most useful for historic events - a timestamp recording exactly when something occurred. For example, a time-zone can be used when the event is viewed in a GUI (and different users might view the event as having happened at a different local time, even though it was the same instant). By minimising what you can do with it (no addition of months/years) it gains clarity and strength as a concept.
LocalDate
is most useful for business logic, particularly where legal contracts are involved. In many cases, a contract will run from a certain date to another date. For example, a financial trade or insurance.
LocalTime
is also useful for business logic, covering the time aspect of contracts. For example, "your car insurance is valid until midday on the date of expiry".
ZonedDateTime
is the essential part for all the nasty hairy DST time-zone math. Its exists to allow a period of years/months/days to be added while taking into account the time-zone. It also allows questions like if I take off at 09:00 on Monday and the flight takes 10 hours what local time will it be when I land in Rio? Or am I currently in a DST overlap where the same local time happens twice? The methods withZoneSameInstant
, withZoneSameLocal
, withEarlierOffsetAtOverlap
and withLaterOffsetAtOverlap
are all key to tackling the really hard date-time math problems - sorry, but there are no shortcuts here.
In JSR-310, ZonedDateTime
is built on LocalDate
, LocalTime
, an offset (+01:00) and a time-zone. So why not a ZonedInstant
built on Instant
and a time-zone?
Well as I indicate above, the reason for wanting the type in the first place is to do date-time math on it. ie. math on date and time. If you just want math on an instant then just use Instant
. ie. the time-zone only has any relevance when considering the impact on date and time fields (particularly years/months). And by corollary, an Instant
can't take into account DST effects (except by passing the zone in to each method call, which is just a horrible user experience).
Does this API have to use the same four fields internally as JSR-310? No. but I found that the most efficiently approach in JSR-310 given the primary use case of date-time math. Having to constantly convert from an Instant
to date-time fields and back again to do the math would have been slow and unappealing. I suspect the same is true here, but it is much more important to focus on the API methods rather than the state the type contains.
And the name? Well since its raison d'etre is to manipulate date and time with zone effects, ZonedDateTime
is about as good a name as you'll get.
I would like to see reasonable side-by-side comparisons of ZonedInstant vs. ZonedDateTime, including cases with DST effects because that's where the difference is likely to matter most.
After long discussion I think we have come to the conclusion reflected in #97 and the polyfill.
TL;DR
The object should be ZonedDateTime
and follow the proleptic Gregorian calendar with a 24h midnight based day. It is the object that ties Instant
objects to a specific calendar implementation. So you could see it as the glue that binds Instant
to the Civil
-family.
Can we close this?
It looks like you simply renamed ZonedInstant to ZonedDateTime, but did not change the specification.
You specified ZonedDateTime
as 'A point on the universal timeline, with an associated time zone.' If you stick to that spec, please call it ZonedInstant
! That name fits much better. And otherwise you would make the confusion complete for all developers that knows Java and Javascript. You would not only use different names for the same domains (because you use Civil
instead of the Local
Prefix) but also use the same name for different domains.
A ZonedDateTime as defined in JSR-310 is a local date-time with a time-zone and a zone offset used to handle ambiguous local date-times. That's something different. And as already stated above, in my opinion the ZonedDateTime
domain is much more suitable to express real world developer problems.
I'll restate what I said earlier:
Does this API have to use the same four fields internally as JSR-310? No. but I found that the most efficient approach in JSR-310 given the primary use case of date-time math. Having to constantly convert from an Instant to date-time fields and back again to do the math would have been slow and unappealing. I suspect the same is true here, but it is much more important to focus on the API methods rather than the state the type contains.
ie. the state is less important than the API methods. (But I do think the class should be described in terms of date and time, not instant).
There are some important differences between Instant and ZonedDateTime, although not all of #120 has yet made it into the README and spec text.
Z
vs. ±hh:mm[IANA zone]
)How would you change that?
I would expect that the API allows me to construct a ZonedDateTime with a given local datetime and a timezone. eg. const zonedDateTime = someLocalDateTime.atZone(europeBerlin)
. Thats for me the natural way how to express a certain point in time. 'I am sitting at a certain location, looking at a calender and a clock at the wall'.
Therefore i would describe a ZonedDateTime as a local date time
with a timezone
and specify a strategy
how to handle ambiguous local date-times, how to calculate an offset/ instant for the three cases: normal, gap and overlap during daylight saving transitions. Like for example in JSR-310 its specified that in an overlap situation the previous offset will be retained, if possible.
Adding the additional methods withEarlierOffsetAtOverlap()
and withLaterOffsetAtOverlap()
might be raryly used, but give me the control to pick the desired instant and helps a lot to understand how the API works.
And i would add the two methods .withZoneSameInstant(timeZone)
and .withZoneSameLocal(timeZone)
. That allows to write up calculations in a very readable way.
I would expect that the API allows me to construct a ZonedDateTime with a given local datetime and a timezone. eg.
const zonedDateTime = someLocalDateTime.atZone(europeBerlin)
. Thats for me the natural way how to express a certain point in time. 'I am sitting at a certain location, looking at a calender and a clock at the wall'.
That should be possible like const zonedDateTime = (new CivilDateTime(2019, 5, 30, 14, 45)).withZone("Europe/Berlin")
.
Therefore i would describe a ZonedDateTime as a
local date time
with atimezone
and specify astrategy
how to handle ambiguous local date-times, how to calculate an offset/ instant for the three cases: normal, gap and overlap during daylight saving transitions. Like for example in JSR-310 its specified that in an overlap situation the previous offset will be retained, if possible.
Right, just like we need disambiguation control for month/year arithmetic in plus
, we also need it for offset transitions in both plus
and withZone
.
Adding the additional methods
withEarlierOffsetAtOverlap()
andwithLaterOffsetAtOverlap()
might be raryly used, but give me the control to pick the desired instant and helps a lot to understand how the API works.
I personally feel like those are better handled as available disambiguation values for the existing methods rather than as new methods.
And i would add the two methods
.withZoneSameInstant(timeZone)
and.withZoneSameLocal(timeZone)
. That allows to write up calculations in a very readable way.
I don't know if we'll go this far. Assuming you already have a {Offset,Zoned}DateTime dt
, the former can be dt.instant.withZone(timeZone)
and probably also dt.withZone(timeZone)
(at least per current documentation in which instant data is preferred over civil), while the latter can be CivilDateTime.from(dt).withZone(timeZone)
.
(Coming to this very late.) To be clear: The plan is to have ZonedDateTime
, right? This issue is only still open because...there are API issues to resolve? It's just confusing (to me) to have an open issue called "Why did you drop ZonedDateTime?" when ZonedDateTime
is prominently explained in the explainer, part of the current object models shown, etc. :-) TIA
In the commit that removed ZonedDateTime from the README.md there is no comment about it and i couldn't find any discussions about that topic. Should ZonedInstant be a replacement ?
A date/ time API should define a consistent language for domains, that makes time and date values easy to manage, manipulate, and understand.
ZonedDateTime
, as defined in theJSR-310 API
, comply quite well with such requirements. It contains the local time, a timezone and an offset. Together with the methodswithZoneSameInstant
,withZoneSameLocal
,withEarlierOffsetAtOverlap
andwithLaterOffsetAtOverlap
it is quite easy to untangle even complicated use case, e.q.:An Instant is a point in the timeline with the UTC timezone. Isn't a Instant more a technical thing, for technical use cases, like for comparing timestamps from different sources at server side. How can i define 'human readable' use cases with it ?
And isn't a ZonedInstant the same as an Instant, both define a point in the timeline at a certain timezone ?