C#在ToInt64中获取特定日期(毫秒)

时间:2018-07-02 17:58:43

标签: c# datetime

我只是想不通...。请参阅第二个代码段中的调用方法。您将看到一条注释为 // _ time = time.ToUTCString(); 的行,转到第一个代码段以查看方法 ToUTCString()。您会看到它需要日期时间,将其转换为世界时,然后减去UnixEpoch即可得出TotalSeconds。然后,它将值转换为Int64(),最后转换为字符串。我尝试调用方法ToLocalString,但这也在更改日期。

我传递的日期是我想要转换为Int64并最终转换为字符串的日期。我传递的日期时间。未更改。

我不想更改传入的日期。我总是传入从12:00:00 AM(或00:00:00)开始的日期,而这正是我一直想要的时间。 这两种方法都会更改日期和/或时间。我传递的日期为 2017年6月1日上午12:00:00 ,但有时它更改为 2017年5月31日04:00:00 或保留日期,但时间不正确。 Dark Sky要求日期为Convert.ToInt64(milliseconds)的值,​​然后转换为字符串。

有人知道如何以毫秒为单位将传入的确切日期和时间转换为Int64吗?

我有以下扩展类:

public static class Extensions
{
    private static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);

    public static DateTime ToDateTime(this Int64 _input)
    {
        return UnixEpoch.AddSeconds(_input);
    }

    public static string ToLocalString(this DateTime _input)
    {
        // _input = {6/1/2017 12:00:00 AM}  System.DateTime
        var milliseconds = _input.ToLocalTime().Subtract(UnixEpoch).TotalSeconds;
        return Convert.ToInt64(milliseconds).ToString();
        // I want to get the milliseconds for {6/1/2017 12:00:00 AM}
        // I don't want the date or time to change
    }

    public static string ToUTCString(this DateTime _input)
    {
        // _input = {6/1/2017 12:00:00 AM}  System.DateTime
        var milliseconds = _input.ToUniversalTime().Subtract(UnixEpoch).TotalSeconds;
        return Convert.ToInt64(milliseconds).ToString();
        // I want to get the milliseconds for {6/1/2017 12:00:00 AM}
        // I don't want the date or time to change
    }
}

这是调用方法:

    public ForecastIORequest(string apiKey, float latF, float longF, DateTime time, Unit unit, Language? lang = null, Extend[] extend = null, Exclude[] exclude = null)
    {
        _apiKey      = apiKey;
        _latitude    = latF.ToString(CultureInfo.InvariantCulture);
        _longitude   = longF.ToString(CultureInfo.InvariantCulture);
        //_time      = time.ToUTCString();
        _time        = time.ToLocalString();
        //DateTime t = _time.
        _unit        = Enum.GetName(typeof(Unit), unit);
        _extend      = (extend != null) ? RequestHelpers.FormatExtendString(extend) : "";
        _exclude     = (exclude != null) ? RequestHelpers.FormatExcludeString(exclude) : "";
        _lang        = (lang != null) ? RequestHelpers.FormatLanguageEnum(lang) : Language.en.ToString();
    }

2 个答案:

答案 0 :(得分:2)

您在这里处理日期的方式存在一个基本问题,如果我将其归结为一件事,我认为问题在于ToUniversalTime()不能像您认为的那样工作。< / p>

ToUniversalTime()的作用是,简单地给UTC一个在不同时区中定义的时间。例如,假设我的当地时间是UTC-7。因此,如果我定义一个DateTime对象而未指定DateTimeKind 并将其值设置为2017/6/1 9:00:00,则意味着当时实际的{{1 }}时间是UTC,此时2017/6/1 16:00:00将为您提供一个具有该值的ToUniversalTime()对象。

让我稍微更改您的DateTime方法,然后向您展示它的问题。它现在返回的是ToUTCString()而不是long的值,我将第一行代码分解为两行。

string

请注意,在您的public static long ToUTC(this DateTime _input) { var utcTime = _input.ToUniversalTime(); var totalSeconds = utcTime.Subtract(UnixEpoch).TotalSeconds; return Convert.ToInt64(totalSeconds); } 类中,Extensions对象的UnixEpoch被设置为DateTimeKind。为了便于理解,我将日期更改为UTC

2017/6/1 8:00:00

现在让我们使用private static readonly DateTime UnixEpoch = new DateTime(2017, 6, 1, 8, 0, 0, DateTimeKind.Utc); public static DateTime ToDateTime(this Int64 _input) { return UnixEpoch.AddSeconds(_input); } 对象设置为DateTime的{​​{1}}对象调用该方法。

DateTimeKind

现在,这里所有内容都在UTC中,您应该看到预期的输出,如下所示:

  

3600

     

6/1/2017 09:00:00

到目前为止一切都很好。

现在要稍作更改,就像在示例中一样,将// dateObj will have time 2017/6/1 9:00:00 _in UTC_. var dateObj = new DateTime(2017, 6, 1, 9, 0, 0, DateTimeKind.Utc); // This method converts to UTC, but it's already in UTC, so no actual conversion takes place. // Then subtracts UnixEpoch from it, which is also in UTC. long dateInLong = dateObj.ToUTC(); // The difference is one hour, so dateInLong will be 3600. Console.WriteLine(dateInLong); // This method adds the above difference to UnixEpoch, and displays the time. Console.WriteLine(dateInLong.ToDateTime()); 设置为local而不是UTC

dateObj

现在,以上UTC将有时间// Notice that the object is in local time now. var dateObj = new DateTime(2017, 6, 1, 9, 0, 0); long dateInLong = dateObj.ToUTC(); Console.WriteLine(dateInLong); Console.WriteLine(dateInLong.ToDateTime()); 但是我的本地时间。我的实际位置是dateObj,所以请注意,这意味着9:00:00对我来说是当地时间UTC-7 UTC。但是请注意,我们尚未更改9AM对象,该对象仍位于4PM中,并且时间设置为UnixEpoch。因此,UTC将是8AM UTC(8小时x 60分钟x 60秒)。因此,在调用您的dateInLong方法时,它会将28,800的时间增加ToDateTime()秒,并作为28,000对象返回,该对象现在的时间为8AM UTC

  

28800

     

6/1/2017 16:00:00

这就是为什么取决于您设置DateTime的时间,输出更改的时间,如您所说的那样。


解决方案

您需要确定要使用的时区,并遵守该时区。一种选择是摆脱所有4PM UTC的转化,并在当地时间设置所有时间。

dateObj

另一个选项,将EVERYTHING设置为UTC,但随后必须确保调用UTC的{​​{1}}对象是在UTC中定义的,而不是本地的。

所以:

public static class Extensions
{
    // NOT set to UTC
    private static readonly DateTime UnixEpoch = new DateTime(2017, 6, 1, 8, 0, 0);

    public static DateTime ToDateTime(this Int64 _input)
    {
        return UnixEpoch.AddSeconds(_input);
    }

    public static long ToUTC(this DateTime _input)
    {
        // NOT converted to UTC. So... change variable names accordingly.
        var utcTime = _input;
        var totalSeconds = utcTime.Subtract(UnixEpoch).TotalSeconds;
        return Convert.ToInt64(totalSeconds);
    }
}

class Program
{
    static void Main(string[] args)
    {
        // Notice that the object is in local time and NOT UTC.
        var dateObj = new DateTime(2017, 6, 1, 9, 0, 0);
        long dateInLong = dateObj.ToUTC();
        Console.WriteLine(dateInLong);
        Console.WriteLine(dateInLong.ToDateTime());
        Console.ReadLine();
    }
}

DateTime

最后

ToUTC()

但是...

在第二个代码段中,您遇到了一个更大的问题。在private static readonly DateTime UnixEpoch = new DateTime(2017, 6, 1, 8, 0, 0, DateTimeKind.Utc); 构造函数中,您将时间节省为var utcTime = _input.ToUniversalTime(); 。我认为这不是理想的解决方案。因为当您发现困难的方式时,根据创建调用对象的时区,您的时差会有所不同。而且您无法知道哪个。

我宁愿按原样存储var dateObj = new DateTime(2017, 6, 1, 9, 0, 0, DateTimeKind.Utc); 对象,并在考虑到时区的情况下读取它并在需要时计算差值。

希望这会有所帮助。

答案 1 :(得分:1)

请参见DateTime.Ticks-一毫秒内有10,000个滴答声。只需花费DateTime.Ticks / 10000(一万),就可以计算出毫秒数。

这是一种简单的扩展方法,可将毫秒数设为长整数(即Int64):

public static long ToMilliseconds(this DateTime dateTime)
{
    return dateTime.Ticks / 10000;
}