Roman Pushkin
Roman Pushkin

Reputation: 6079

Proper way of .Net timezone validation

I have a method that accepts .Net (or windows) timezone id as a string:

public void SaveTimezoneId(string timezoneId) { ... }

As you may know, timezones in .Net are strings like this:

etc.

Before saving them to database, I need a way to validate them. What I do now looks like this:

    try
    {
        TimeZoneInfo.FindSystemTimeZoneById(timezoneId);

        CurrentUser.TimezoneId = timezoneId;
        context.SaveChanges();

        return JsonSuccess();
    }
    catch(Exception)
    {
        return JsonError("Invalid time zone");
    }

But it completely breaks one of the main principles of good software development: never rely on exceptions. And moreover, exceptions are expensive.

Is there any other way to perform this check and get rid of try-catch?

Thanks.

Upvotes: 6

Views: 3350

Answers (1)

Lasse V. Karlsen
Lasse V. Karlsen

Reputation: 391306

First of all, if you don't have an alternative, or the alternative is (also) costly, then Exceptions are the way to go. I'm not asking you to stop looking for alternatives, but don't ban exceptions, they have their place as do all types of code.

However, you have an alternative, you can call TimeZoneInfo.GetSystemTimeZones and do the lookup yourself:

void Main()
{
    var timeZones = TimeZoneInfo
        .GetSystemTimeZones()
        .ToDictionary(stz => stz.Id);

    TimeZoneInfo tz;
    if (timeZones.TryGetValue("UTC-11", out tz))
        tz.Dump();
    else
        Debug.WriteLine("No such timezone");
}

If you only need to know if a the id is valid:

void Main()
{
    var timeZoneIds = new HashSet<string>(TimeZoneInfo
        .GetSystemTimeZones()
        .Select(tzi => tzi.Id));

    timeZoneIds.Contains("UTC-11").Dump();
}

Both of these can be tested in LINQPad.

If you need to do the lookup/check many times and can spare some memory to pay for some speed, you can store the dictionary/hashset somewhere safe between calls.

Upvotes: 9

Related Questions