leora
leora

Reputation: 196751

How to convert a time and olson timezone to the time in another olson timezone?

I have as an input:

  1. The time (8:00AM)
  2. An Olson Timezone (America/New_York)

and I need to convert the time into another Olson Timezone (America/Los_Angeles)

What is the best way in .net or nodatime to do that conversion. I am basically looking for the equivalent of this method in C#:

  var timeInDestinationTimeZone = TimeZoneInfo.ConvertTimeBySystemTimeZoneId(CurrentSlot.Date, TimeZoneInfo.Local.Id,
                                                                            room.Location.TimeZone.TimeZoneName);

but this .Net method above only works with Windows Timezone names (and i have Olson names)

Upvotes: 3

Views: 2733

Answers (2)

Jon Skeet
Jon Skeet

Reputation: 1502835

An alternative to the second part of Matt's (perfectly good) answer:

// All of this part as before...
var tzdb = DateTimeZoneProviders.Tzdb;    
var zone1 = tzdb["America/New_York"];
var ldt1 = new LocalDateTime(2013, 3, 4, 8, 0); // March 4th, 2013 - 8:00 AM
var zdt1 = zone1.AtLeniently(ldt1);

var zone2 = tzdb["America/Los_Angeles"];

// This is just slightly simpler - using WithZone, which automatically retains
// the calendar of the existing ZonedDateTime, and avoids having to convert
// to Instant manually
var zdt2 = zdt1.WithZone(zone2);
var ldt2 = zdt2.LocalDateTime;

Upvotes: 3

Matt Johnson-Pint
Matt Johnson-Pint

Reputation: 241788

Observe:

var tzdb = DateTimeZoneProviders.Tzdb;

var zone1 = tzdb["America/New_York"];
var ldt1 = new LocalDateTime(2013, 3, 4, 8, 0); // March 4th, 2013 - 8:00 AM
var zdt1 = zone1.AtLeniently(ldt1);

var zone2 = tzdb["America/Los_Angeles"];
var zdt2 = zdt1.ToInstant().InZone(zone2);
var ldt2 = zdt2.LocalDateTime;

Notice the call to AtLeniently - that's because you don't have enough information to be absolutely certain of the moment in time you are talking about. For example, if you were talking about 1:30 AM on the day of a DST fall-back transition, you wouldn't know if you were talking about before or after the transition. AtLeniently will make the assumption you meant after. If you don't want that behavior, you have to provide an offset so you know which local time you were talking about.

The actual conversion is being done by ToInstant which is getting the UTC moment you're talking about, and then InZone which is applying it to the target zone.

Upvotes: 5

Related Questions