3

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)

leora
  • 188,729
  • 360
  • 878
  • 1,366
  • possible duplicate of [.NET TimeZoneInfo from Olson time zone](http://stackoverflow.com/questions/5996320/net-timezoneinfo-from-olson-time-zone) – 500 - Internal Server Error Mar 04 '13 at 04:40
  • 1
    this is not a duplicate. the other question is asking to map to windows timezone. I don't want to do that. I just want to convert time and keep all timezone info in olson format – leora Mar 04 '13 at 04:50
  • Could you not go via Windows time zone and do the conversion there? – 500 - Internal Server Error Mar 04 '13 at 05:00
  • 1
    Yes but that causes an extra layer of complication and fidelity loss given all of the issue between mapping across. That is exactly the reason i am asking the question as i don't want to convert to Windows time – leora Mar 04 '13 at 05:15
  • Take a look at Jon Skeet's [Noda Time](https://code.google.com/p/noda-time/) – Aron Mar 04 '13 at 07:16
  • 1
    I have listed nodatime in my question . . that is my question :) – leora Mar 04 '13 at 13:36
  • [MSDN Converting Times Between Time Zones](http://msdn.microsoft.com/en-us/library/bb397769.aspx) – Alina B. Mar 04 '13 at 16:49
  • @Alina - this doesn't answer my question as it assumes you already have windows timezone names. I do not – leora Mar 04 '13 at 20:41
  • Not sure why everyone wants to close this. This is a valid question, and not a duplicate. – Matt Johnson-Pint Mar 05 '13 at 00:00
  • I found another similar thread [Convert Olson to Standard Timezone](http://stackoverflow.com/questions/5996320/net-timezoneinfo-from-olson-time-zone). – Alina B. Mar 05 '13 at 04:37
  • @AlinaB. The two threads referenced are duplicates of each other, but neither is what this question is about. This question is strictly about proper use of NodaTime for converting time between two Olson time zones. The other questions are about mapping between Windows timezones and Olson timezones. – Matt Johnson-Pint Mar 06 '13 at 00:13

2 Answers2

5

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.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
3

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;
Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
  • @Jon Skeet - I had to give Matt the accept as I used it and it worked well (and you have plenty of accepted answers :) ). Spent lots of time yesterday reading through the NodaTime docs and learned tons ..thanks for taking the time to put this libarary together . . – leora Mar 05 '13 at 05:50
  • @leora: I'm glad it's coming together for you - please send the mailing list any feedback on where we could improve the docs. – Jon Skeet Mar 05 '13 at 12:42