Time zones in Xamarin.Forms

Time zones conversions are sometimes required in mobile apps from your local time zone to another, non-UTC time zone. Time zones can be tricky due to daylight savings, meaning an offset from UTC can change during the year for a particular location. Politics can even skew this further by making daylight savings changes, as to when it is implemented.

The operating system. keeps a database of all time zones and daylight saving changes, and it updates it as necessary. It is best if you can use this, for your time zone conversions.

Of course, if you can, its always best to just use UTC time, or DateTimeOffset and let your API backend do any time conversions. But if you need a to see a different non-UTC local timezone, then here are your options.

.NET Standard

If you are using .NET standard, this is fairly easy. But you will need to use Device.RuntimePlatform to choose the right time zone identifier for the platform you are on.

Android and iOS

Android and iOS use IANA timezone names. They look like this “America/New_York” and you can find a list of them at the List of tz database time zones.

TimeZoneInfo estZone = TimeZoneInfo.FindSystemTimeZoneById("America/New_York");
DateTime estTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, estZone);


Windows, uses its own names, They look like this “Eastern Standard Time” and you can find a list of them at the Microsoft Time Zone Index Values.

TimeZoneInfo estZone = TimeZoneInfo.FindSystemTimeZoneById("Eastern Standard Time");
DateTime estTime = TimeZoneInfo.ConvertTimeFromUtc(timeUtc, estZone);

PCL or Other Platform

If you need a PCL solution, or if the platform you are working on doesn’t have any timezone information, then you can do it manually and keep your own Time zone database. The best database you can get, comes in the form of some CSV files from Timezonedb. You just need the zone.csv and timezone.csv files, from the download, and place them in your app.

While I leave it up to you to read them, as this differs for every platform, here is some code to to load them up and then do a time zone conversion.

First create the classes needed to store the information.

public class Zone
    public int Code { get; set; }
    public string CountryCode { get; set; }
    public string Name { get; set; }

public class Timezone
    public int Id { get; set; }
    public string Abbreviation { get; set; }
    public long TimeStart { get; set; }
    public int GMTOffset { get; set; }
    public bool DST { get; set; }

Now we need to create a list of zones and time zones to do a conversion.

var zones = new List<Zone>();
var timezones = new List<Timezone>();

var reader = new StreamReader(@"zone.csv");
while (!reader.EndOfStream)
    var line = reader.ReadLine();
    var values = line.Split(',');

    var zone = new Zone()
        Code = Convert.ToInt32(values[0].Trim('"')),
        CountryCode = values[1].Trim('"'),
        Name = values[2].Trim('"')

reader = new StreamReader(@"timezone.csv");
while (!reader.EndOfStream)
    var line = reader.ReadLine();
    var values = line.Split(',');

    var timezone = new Timezone()
        Id = Convert.ToInt32(values[0].Trim('"')),
        Abbreviation = values[1].Trim('"'),
        TimeStart = Convert.ToInt64(values[2].Trim('"')),
        GMTOffset = Convert.ToInt32(values[3].Trim('"')),
        DST = Convert.ToBoolean(Convert.ToInt32(values[4].Trim('"')))


Next we implement the conversion.

DateTime ConvertDateTime(DateTime from, string fromTimezone, string toTimezone)
    var unixTimestamp = (Int32)(from.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;

    var fromZoneId = zones.First(x => x.Name == fromTimezone).Code;
    var toZoneId = zones.First(x => x.Name == toTimezone).Code;

    var fromTimezones = timezones.Last(x => x.Id == fromZoneId && x.TimeStart <= unixTimestamp);
    var toTimezones = timezones.Last(x => x.Id == toZoneId && x.TimeStart <= unixTimestamp);

    var secondTransition = toTimezones.GMTOffset - fromTimezones.GMTOffset;

    return DateTime.Now.AddSeconds(secondTransition);

// Uses the IANA naming
var convertedTime = ConvertDateTime(DateTime.Now, "Australia/Melbourne", "Australia/Perth");

While this works well, you now have the responsibility in having to maintain the csv files in your app and publishing a new app version, every time these need updating. Sticking to a platform maintained list, is much easier. Timezonedb also offer an API if you want to use that, but it may cause too much delay, waiting for an API to convert a time. In this case, I would just create and update your own API to provide it, instead.

Remember that time zone conversions on mobile apps should only be used to help guide the user. Your API should provide actual conversions from UTC or with a DateTimeOffset, and have checks in place, as needed.

One Comment