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?

有帮助吗?

解决方案

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.

许可以下: CC-BY-SA归因
不隶属于 StackOverflow
scroll top