user247702
user247702

Reputation: 24222

Parsing user input including tz database time zone name

I'm attempting to parse user input with Noda Time.

Input:

I need to convert this data to UTC and to other time zones, also based on a tz database time zone name.

Currently I'm trying to make sense of the LocalDateTime and ZonedDateTime differences, but perhaps someone is able to show how to do this before I'd (hopefully) figure this out.

Upvotes: 1

Views: 456

Answers (2)

Jon Skeet
Jon Skeet

Reputation: 1502825

Your answer is pretty close to what I'd do - but if you have the date, hour and minute in separate strings, I'd use:

var zoneProvider = DateTimeZoneProviders.Tzdb;
var sourceZone = zoneProvider.GetZoneOrNull("Europe/Brussels");
var targetZone = zoneProvider.GetZoneOrNull("Australia/Melbourne");

if (sourceZone == null || targetZone == null)
{
    Console.WriteLine("Time zone not found");
    return;
}

var dateParseResult = LocalDatePattern.IsoPattern.Parse(date);
int hourValue, minuteValue;
if (!dateParseResult.Success ||
    !int.TryParse(hour, out hourValue) ||
    !int.TryParse(minute, out minuteValue))
{
    Console.WriteLine("Parsing failed");
    return;       
}

var localDateTime = dateParseResult.Value + new LocalTime(hour, minute);
var zonedDateTime = localDateTime.InZoneStrictly(sourceZone);
Console.WriteLine(zonedDateTime.ToInstant());
Console.WriteLine(zonedDateTime);
Console.WriteLine(zonedDateTime.WithZone(targetZone));

The only significant difference here is the parsing - I wouldn't stick all the bits together; I'd just parse the strings separately. (I also prefer "early outs" for failures :)

You should note the meaning of InZoneStrictly though - do you definitely want to fail if the input local date/time is ambiguous?

Upvotes: 1

user247702
user247702

Reputation: 24222

http://msmvps.com/blogs/jon_skeet/archive/2012/02.aspx has great information, and while it's slightly outdated it's easy to find the relevant method names in the official documentation.

Below is some demonstration code.

string date = "2013-01-22";
string hour = "13";
string minute = "15";

var result = LocalDateTimePattern.ExtendedIsoPattern.Parse(date + "T" + hour + ":" + minute + ":00");

if (result.Success == true)
{
    DateTimeZone source_zone = DateTimeZoneProviders.Tzdb.GetZoneOrNull("Europe/Brussels");
    DateTimeZone target_zone = DateTimeZoneProviders.Tzdb.GetZoneOrNull("Australia/Melbourne");

    if (source_zone != null && target_zone != null)
    {
        ZonedDateTime source_zoned_dt = result.Value.InZoneStrictly(source_zone);

        Console.WriteLine(source_zoned_dt.ToInstant());
        Console.WriteLine(source_zoned_dt);
        Console.WriteLine(source_zoned_dt.WithZone(target_zone));
    }
    else
    {
        Console.WriteLine("time zone not found");
    }
}
else
{
    Console.WriteLine("parsing failed");
}

Upvotes: 1

Related Questions