I would like to convert specific date time value to UTC with NodaTime by giving country code.
For example country is Turkey, country code is TR and specific date time is "Feb 5, 2016 7:45 PM" it would be "Feb 5, 2016 5:45 PM" is it possible?
Also my windows location is not Turkey.
Thank you in advance?
Well, you can't do it just with a country code - you need a time zone. In some countries there are multiple time zones.
Once you have a time zone as a DateTimeZone
(either via a BCL TimeZoneInfo
or from the TZDB time zone provider) you would:
LocalDateTime
from the value you've got, e.g. using LocalDateTimePattern
to parse textLocalDateTime.InZoneLeniently
(or similar - more about that in a moment) to get the ZonedDateTime
WithZone(DateTimeZone.Utc)
to convert it to a UTC-based ZonedDateTime
The part about InZoneLeniently
, InZoneStrictly
or InZone(DateTimeZone, ZoneLocalMappingResolver)
is because a local date and time might occur twice or not at all, around DST transitions. See the user guide for more details on that.
Sample code:
using System;
using NodaTime;
using NodaTime.Text;
class Test
{
static void Main()
{
var text = "Feb 5, 2016 7:45 PM";
var zone = DateTimeZoneProviders.Tzdb["Europe/Istanbul"];
var pattern = LocalDateTimePattern.CreateWithInvariantCulture("MMM d, YYYY h:mm tt");
var local = pattern.Parse(text).Value;
var zoned = local.InZoneStrictly(zone);
var utc = zoned.WithZone(DateTimeZone.Utc);
Console.WriteLine(utc); // 2016-02-05T17:45:00 UTC (+00)
}
}
Now, for finding the time zone from a country code, the TZDB (IANA) database comes with information about time zone locations, which is exposed in Noda Time. For example, if you have an ISO-3166 2-letter country code, you could use:
using NodaTime;
using NodaTime.TimeZones;
using System.Linq;
...
var code = "TR"; // Turkey
var zoneId = TzdbDateTimeZoneSource.Default.ZoneLocations
.Single(loc => loc.CountryCode == code)
.ZoneId;
var zone = DateTimeZoneProviders.Tzdb[zoneId];
The Single
call will fail if there's more than one zone with the given country code (or none).
If you're going to frequently look up the zones, you might want to build a dictionary:
var zonesByCountryCode = TzdbDateTimeZoneSource.Default
.ZoneLocations
.GroupBy(loc => loc.CountryCode)
.Where(g => g.Count() == 1) // Single-zone countries only
.ToDictionary(g => g.Key, g => g.First());
See more on this question at Stackoverflow