0

I am using the code mentioned on this link. I didn't understand the purpose of InZoneLeniently, Could someone explain by any real-time example when it is needed or when not needed?

I have started using NodaTime. If there are any changes in the IANA time zone or for example they add a new time zone. Then will we need to upgrade the nodatime library or will it handle it? In my case, I need to handle these conversions, but there may be more of a difference in future.

  1. Europe/London to America/Chicago
  2. Europe/Berlin to America/Chicago
  3. America/New_York to America/Chicago
Vivek Nuna
  • 25,472
  • 25
  • 109
  • 197

1 Answers1

1

Firstly, InZoneLeniently isn't used when converting from one time zone to another - it's used when converting from a LocalDateTime (with no offset information) to a ZonedDateTime.

Background from the [documentation]:

As well as mapping any particular instant to an offset, DateTimeZone allows you to find out the name of the part of the time zone for that instant, as well as when the next or previous change occurs - usually for daylight saving changes.

Most of the time when you use a DateTimeZone you won't need worry about that - the main purpose is usually to convert between a ZonedDateTime and a LocalDateTime, where the names mean exactly what you expect them to. There's a slight twist to this: converting from an Instant or a ZonedDateTime to a LocalDateTime is unambiguous; at any point in time, all the (accurate) clocks in a particular time zone will show the same time... but the reverse isn't true. Any one local time can map to:

  • A single instant in time: this is the case for almost all the time.
  • Two instants in time: this occurs around a time zone transition which goes from one offset to an earlier one, e.g. turning clocks back in the fall. If the clocks go back at 2am local time to 1am local time, then 1.30am occurs twice... so you need to tell Noda Time which of the possibilities you want to account for.
  • Zero instants in time: this occurs around a time zone transition which goes from one offset to a later one, e.g. turning clocks forward in the spring. If the clocks go forward at 1am local time to 2am local time, then 1.30am doesn't occur at all.

So for example, mapping a LocalDateTime to a ZonedDateTime in Europe/London, bearing in mind that on March 27th 2022, we had a "spring forward" from 1am to 2am at the start of summer time, and on October 30th 2022 we'll have a "fall back" from 2am to 1am.

  • A local date/time of 2022-10-07T16:00:00 is unambiguously mapped to 2022-10-07T15:00:00+01 in London
  • A local date/time of 2022-10-30T01:30:00 is ambiguous - it happens twice because the local time goes back from 2am to 1am. It could map to 2022-10-30T01:30:00Z or 2022-10-30T01:30:00+01.
  • A local date/time of 2022-03-27T01:30:00 would be invalid - it's skipped because the local time skips forward from 1am to 2am.

As the documentation for LocalDateTime.InZoneLeniently states:

Returns the mapping of this local date/time within the given DateTimeZone, with "lenient" rules applied such that ambiguous values map to the earlier of the alternatives, and "skipped" values are shifted forward by the duration of the "gap".

So in the cases above:

  • Input of 2022-10-07T16:00:00 (London) would return 2022-10-07T10:00:00 (Chicago) - it's unambiguous
  • Input of 2022-10-30T01:30:00 (London) would return 2022-10-30T01:30:00+01 - the earlier of the ambiguous alternatives
  • Input of 2022-03-27T01:30:00 (London) would return 2022-03-27T02:30:00+01 - the value is shifted forward by an hour (which is the length of the DST gap).

So you need to ask yourself: if you've only got a local date/time in your app, what do you want to do if that local date/time was skipped or ambiguous? If InZoneLeniently doesn't do what you want, there's InZoneStrictly(DateTimeZone) or InZone(DateTimeZone, ZoneLocalMappingResolver).

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • Thank you for the detailed info, so If I use `InZoneLeniently` then it will consider daylight saving time? If I use another option it will not consider DST? so for example, If I use `InZoneLeniently` then it will give me BST otherwise GMT for today's date? – Vivek Nuna Oct 07 '22 at 16:06
  • Is there a simple way to convert from one time zone to another with handling the DST cases like in C# we have `var convertedTime = TimeZoneInfo.ConvertTime(inputDateTime, fromTimeZone, toTimeZone);`? – Vivek Nuna Oct 07 '22 at 16:23
  • @viveknuna: Of course it will consider daylight saving time - it would be a pretty broken time zone conversion if it assumed a fixed offset. I don't know what you mean by "otherwise GMT for today's date". There isn't *any* conversion you could do in Noda Time from LocalDateTime to the Europe/London time zone that would give you an offset of 0 (GMT) for today's date, because that would just be *wrong*. It's still not clear to me that you've taken the thrust of this answer on board - the difference between InZoneLeniently and InZoneStrictly is *just* in terms of handling skipped/ambiguous times. – Jon Skeet Oct 07 '22 at 16:40
  • @viveknuna: And in terms of time zone conversions: one of the points of using Noda Time is to make you aware of where you need to make decisions. Can you tell me (without consulting the docs) what `TimeZoneInfo.ConvertTime` does if the input value is skipped or ambiguous in `fromTimeZone`? I can't. It should, IMO, be explicit - which is why it *is* explicit in Noda Time. Note that converting from one `ZonedDateTime` to another is trivial using `WithZone`. That's not a problem. The problem is converting from a `LocalDateTime` to a `ZonedDateTime` to start with. – Jon Skeet Oct 07 '22 at 16:42
  • to answer your question, I don't know. I didn't even know this concept before you explained – Vivek Nuna Oct 07 '22 at 16:47
  • I am posting another question now to ask a very specific question – Vivek Nuna Oct 07 '22 at 16:48
  • is there a way to simulate the two instants and Zero instant case by running the application locally which are mentioned in your answer? – Vivek Nuna Oct 07 '22 at 17:56
  • @viveknuna: Just create the `LocalDateTime` values described and perform the conversion. It's not like anything in Noda Time is going to use the current date/time in the conversion. If you want to know *all* the possible outputs, you can use `DateTimeZone.MapLocal`, but that's mainly for internal use - I think it unlikely that you'd really want to use that. – Jon Skeet Oct 07 '22 at 17:57
  • I understand now, please check my updated question. Thank you for answering my silly questions patiently:) – Vivek Nuna Oct 07 '22 at 18:14
  • 1
    @viveknuna: Please roll back the change - that extra information isn't suitable as part of the question. I'll note the DST changes in the answer though. – Jon Skeet Oct 07 '22 at 18:57