Question

Below is the method I use that takes in three inputs:

dateTimeInput which is a string that represents a date.

inputFormat are my format strings like this format: yyyy-MM-dd'T'HH:mm:sszzz.

timeZoneStandardName are unique timezone identifiers retrieved from var TimeZoneList = TimeZoneInfo.GetSystemTimeZones(); where the ID is retrieved via timeZoneList.Id.

I mainly used TimeZoneInfo to get my hours and minute offsets because it's very explicit as to what city/timezone it is, e.g. UTC is the input string.

public int dateTimeToUnixTime(string dateTimeInput, string inputFormat, string timeZoneStandardName)
{
    DateTime result;
    CultureInfo provider = CultureInfo.InvariantCulture;
    TimeZoneInfo objTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZoneStandardName);
    int timeZoneHours = objTimeZoneInfo.BaseUtcOffset.Hours;
    int timeZoneMinutes = objTimeZoneInfo.BaseUtcOffset.Minutes;

    // if input format is "yyyy-MM-dd'T'HH:mm:sszzz"
    if (inputFormat == "yyyy-MM-dd'T'HH:mm:sszzz")
    {
        result = DateTime.ParseExact(dateTimeInput, inputFormat, provider, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
        int unixTime = (Int32)(result.Subtract(Epoch)).TotalSeconds;
        return unixTime;
    }
    else
    {
        // if other input formats
        result = DateTime.ParseExact(dateTimeInput, inputFormat, provider, DateTimeStyles.AssumeUniversal | DateTimeStyles.AdjustToUniversal);
        int unixTime = (Int32)(result.AddHours(-timeZoneHours).AddMinutes(-timeZoneMinutes).Subtract(Epoch)).TotalSeconds;
        return unixTime;
    }
}

My second method takes in a Unix timestamp and a timezone specifier and outputs as a location-dependent time:

public string unixTimeToDateTime(int unixInput, string outputFormat, string timeZoneStandardName)
{
    // output format is "yyyy-MM-dd'T'HH:mm:sszzz"
    TimeZoneInfo objTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZoneStandardName);
    int timeZoneHours = objTimeZoneInfo.BaseUtcOffset.Hours;
    int timeZoneMinutes = objTimeZoneInfo.BaseUtcOffset.Minutes;
    if (outputFormat == "yyyy-MM-dd'T'HH:mm:sszzz")
    {
        System.DateTime dateTime = Epoch.AddSeconds(unixInput);
        return dateTime.AddHours(timeZoneHours).AddMinutes(timeZoneMinutes).ToString("yyyy-MM-dd'T'HH:mm:ss") + toTimeSpan(timeZoneHours, timeZoneMinutes);
    }
    // output format is not
    else
    {
        System.DateTime dateTime = Epoch.AddSeconds(unixInput).AddHours(timeZoneHours).AddMinutes(timeZoneMinutes);
        return dateTime.ToString(outputFormat);
    }
}

For example, here is this method in a Grasshopper component for me to show you what I mean. dateTimeToUnixTime() is my first "clock", while unixTimeToDateTime() is my second "clock"

enter image description here

Given an input of those list of times and a timezone marker of EST, and given those dates (mind you November 2nd 2014 1-2 AM is when we get our DST adjustments again), this method theoretically should adjust its timezone to offset an hour.

I know that TimeZoneInfo supports DST because I can use the below method to show a bool of a respective timezone's DST status.

    var TimeZoneList = TimeZoneInfo.GetSystemTimeZones();

    for (int i = 0; i < TimeZoneList.Count; i++)
    {
        Console.WriteLine(TimeZoneList[i].Id + ": " + TimeZoneList[i].SupportsDaylightSavingTime);
    }

My question is, what is missing in my dateTimeToUnixTime() method that would allow automatic adjustment and offset depending on the DST conditions?

Was it helpful?

Solution

Assuming that your epoch starts at 1/1/1970, then we can use a DateTimeOffset _1970 as your epoch, add the required seconds to _1970 and then use TimeZoneInfo.ConvertTime to get a date time in the specified time zone with daylight savings adjustments (if applicable). It is important to use a DateTimeOffset and not DateTime so that the correct offset will be kept when getting the string.

private static readonly DateTimeOffset _1970 = new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero);
public string UnixTimeToDateTime(int unixInput, string outputFormat, string timeZoneStandardName)
{
    var objTimeZoneInfo = TimeZoneInfo.FindSystemTimeZoneById(timeZoneStandardName);
    var utcDate = _1970.AddSeconds(unixInput);
    DateTimeOffset localDate = TimeZoneInfo.ConvertTime(utcDate, objTimeZoneInfo);
    return localDate.ToString(outputFormat);
}

//1970-01-01T13:00:00+13:00
Console.WriteLine( UnixTimeToDateTime(0, "yyyy-MM-dd'T'HH:mm:sszzz", "New Zealand Standard Time"));

//1970-01-01T08:00:00+08:00
Console.WriteLine(UnixTimeToDateTime(0, "yyyy-MM-dd'T'HH:mm:sszzz", "Singapore Standard Time"));

//1969-12-31T19:00:00-05:00
Console.WriteLine(UnixTimeToDateTime(0, "yyyy-MM-dd'T'HH:mm:sszzz", "Eastern Standard Time"));

It is important to note that using TimeZoneInfo may not have accurate information about historical date adjustments, so if that is important to you, then you may be better using a library such as Node Time.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top