2

I have local time in string format: "yyyy-MM-dd HH:mm:ss" and an IANA Time Zone for that time (e.g. "Europe/London").

How do I convert that in C#, maybe using NodaTime, to a UTC+TimeZone Offset string

e.g. "yyyy-MM-dd HH:mm:ss+01:00" ?

I don't even know where to start!

This is as far as I get (I am afraid I'm new to C sharp): I understand I need to convert it to an instant, but just can't get to grips with the library.

string dateTime = "2014-12-31 12:30:00";
string IANA = "Europe/London";
Instant instDateTime = NodaTime.Instant.FromDateTimeUtc(Convert.ToDateTime(dateTime));
string outputUTC = string.Format("yyyy-MM-dd HH:mm:ssZ", instDateTime);

Thanks to Matt (see answer below), I now have the functions I needed (Note that in the end what I needed was UTC and not date time + offset):

What is a little worrying is that is says that Europe/Moscow is UTC+04:00, whereas it is actually UTC+03:00 since 26 October 2014.

    static void Main(string[] args)
    {
        string dateTime = "2014-12-31T12:30:00";
        string timeZone = "Europe/Moscow";

        Console.WriteLine(timeZone + " Local time '" + dateTime + "' to Zulu time");
        Console.WriteLine(ConvertIANALocalTimeToZulu(timeZone, dateTime));
        Console.WriteLine();
        Console.WriteLine("Zulu time '" + dateTime + "' to " + timeZone + " local time");
        Console.WriteLine(ConvertZuluTimeToIANALocalTime(timeZone, dateTime));

        Console.ReadLine();
    }

    static string ConvertIANALocalTimeToZulu(string timeZoneIANA, string localDateTime)
    {
        var pattern = LocalDateTimePattern.CreateWithInvariantCulture("yyyy-MM-ddTHH:mm:ss");
        LocalDateTime ldt = pattern.Parse(localDateTime).Value;
        ZonedDateTime zdt = ldt.InZoneLeniently(DateTimeZoneProviders.Tzdb[timeZoneIANA]);
        Instant instant = zdt.ToInstant();
        ZonedDateTime zulu = instant.InUtc();
        ////string output = zulu.ToString("yyyy-MM-dd HH:mm:sso<m>", CultureInfo.InvariantCulture);
        string output = zulu.ToString("yyyy-MM-ddTHH:mm:ss", CultureInfo.InvariantCulture);

        return output;
    }

    static string ConvertZuluTimeToIANALocalTime(string timeZoneIANA, string zuluDateTime)
    {
        var pattern = InstantPattern.CreateWithInvariantCulture("yyyy-MM-ddTHH:mm:ss");
        Instant instant = pattern.Parse(zuluDateTime).Value;
        ZonedDateTime zdt = instant.InZone(DateTimeZoneProviders.Tzdb[timeZoneIANA]);
        ////string output = zdt.ToString("yyyy-MM-dd HH:mm:sso<m>", CultureInfo.InvariantCulture);
        string output = zdt.ToString("yyyy-MM-ddTHH:mm:ss", CultureInfo.InvariantCulture);

        return output;
    }
Paul Panayis
  • 47
  • 1
  • 4
  • 5
    Start with posting code. Even horribly broken code allows someone to help you over the first hurdle you didn't clear. – bmike Dec 30 '14 at 16:08
  • Show decent effort and someone will help you ! – mybirthname Dec 30 '14 at 16:24
  • I have read this post in regards to Converting the text from IANA to Windows, but I don't understand what's going on in here. [iana to windows time zone conversion](http://stackoverflow.com/questions/17348807/how-to-translate-between-windows-and-iana-time-zones) – Paul Panayis Dec 30 '14 at 17:11
  • @PaulPanayis - That question is for converting between the IANA system of time zones, and the Microsoft Windows system of time zones - which is not what you appear to be interested in from your post. Read [the timezone tag wiki](http://stackoverflow.com/tags/timezone/info) for more details. – Matt Johnson-Pint Dec 30 '14 at 21:59

1 Answers1

8

It's unclear from your question if you meant that the original value was in UTC or in local time.

If it's in UTC, then do the following:

string dateTime = "2014-12-31 12:30:00";
string timeZone = "Europe/London";

var pattern = InstantPattern.CreateWithInvariantCulture("yyyy-MM-dd HH:mm:ss");
Instant instant = pattern.Parse(dateTime).Value;
ZonedDateTime zdt = instant.InZone(DateTimeZoneProviders.Tzdb[timeZone]);
string output = zdt.ToString("yyyy-MM-dd HH:mm:sso<m>", CultureInfo.InvariantCulture);

If it's in local time, then do this instead:

string dateTime = "2014-12-31 12:30:00";
string timeZone = "Europe/London";

var pattern = LocalDateTimePattern.CreateWithInvariantCulture("yyyy-MM-dd HH:mm:ss");
LocalDateTime ldt = pattern.Parse(dateTime).Value;
ZonedDateTime zdt = ldt.InZoneLeniently(DateTimeZoneProviders.Tzdb[timeZone]);
string output = zdt.ToString("yyyy-MM-dd HH:mm:sso<m>", CultureInfo.InvariantCulture);

Also - you should note that in December, London is on GMT (UTC+00:00) - so the output of either function will be "2014-12-31 12:30:00+00:00" for the values you provided.

Matt Johnson-Pint
  • 230,703
  • 74
  • 448
  • 575
  • Hi Matt, sorry I was not clear. The time I start with is Local time. I am actually looking to convert into Zulu Time, which as I understand more does not include an offset at all? – Paul Panayis Dec 31 '14 at 07:56
  • Thank you for the help above.. It comprehensively answers my question and gives me the start I needed to get to grips with all of this. – Paul Panayis Dec 31 '14 at 08:02
  • Glad to help. Also, note that you can probably simplify your functions quite a bit. If you're using the full ISO8601 format (with the `T` separator), there are properties like `LocalDateTimePattern.GeneralIsoPattern` that help. Also, if you plan to format without offset or `Z`, you can re-use the same `LocalDateTimePattern` instance for both parsing *and* formatting, instead of calling `ToString`. Also, you might consider omitting the `InUTC` step, and formatting the instant directly - as it's already UTC internally. – Matt Johnson-Pint Dec 31 '14 at 18:44
  • Regarding Moscow's time zone, that change was made in the tzdb *after* NodaTime 1.3 was released. NodaTime's embedded data is not self-updating. You have to manage that yourself with external data, as described [in the user guide here](http://nodatime.org/1.3.x/userguide/tzdb.html). – Matt Johnson-Pint Dec 31 '14 at 18:46