代码之家  ›  专栏  ›  技术社区  ›  Patricia

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

  •  -4
  • Patricia  · 技术社区  · 6 年前

    我就是想不出来…该死!请参阅第二个代码段中的调用方法。你会看到一行注释,上面写着 //time=time.toutString(); 转到第一个代码段以查看方法 ToutString() 是的。您可以看到它接受datetime,将其转换为通用时间,然后减去unixepoch得到totalseconds。然后它将该值转换为int64()并最终转换为字符串。我试着打电话给当地人,但那也改变了日期。

    我传入的日期是要转换为Int64并最终转换为字符串的日期。我进去的日期。没有改变。

    我不想更改传入的日期。我总是在12:00:00(或00:00:00)开始的日期,这是我一直想要的时间。 这两种方法都会更改日期和/或时间 是的。我进去的日期是 2017年1月6日上午12:00:00 但有时会变成 2017年5月31日04:00:00 或者它保留了日期但时间错了。Dark Sky要求日期是Convert.ToInt64(毫秒)的值,然后转换为字符串。

    有人知道如何使用毫秒将传入的确切日期和时间转换为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 回复  |  直到 6 年前
        1
  •  2
  •   Sach    6 年前

    你处理日期的方式有一个根本问题,如果我把它归结为一件事,我想问题是 ToUniversalTime() 不是你想的那样。

    什么 时间() 是的,仅仅是给 UTC 在不同时区定义的时间。例如,假设我的本地时间是 UTC-7 是的。所以如果我定义 DateTime 对象 未指定 DateTimeKind 并将值设置为,比如, 2017/6/1 9:00:00 ,也就是说,在那个时候 协调世界时 时间就是 2017/6/1 16:00:00 当时,和 时间() 会给你一个 日期时间 具有该值的对象。

    让我把你的 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 对象的 日期时间类型 设置为 协调世界时 是的。我把日期改成 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);
    }
    

    现在我们用 日期时间 对象 日期时间类型 设置为 协调世界时 是的。

    // 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());
    

    现在,这里,一切都在 协调世界时 您应该看到预期的输出,如下所示:

    3600个

    2017年6月1日09:00:00

    到目前为止一切都很好。

    现在改变一下,让我们 dateObj 到本地而不是 协调世界时 ,正如您在示例中所做的那样。

    // 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());
    

    现在,上面 日期对象 会有时间的 9:00:00 我是说, 但在我的本地时间 .我的实际位置是 协调世界时-7 所以请注意这意味着 9AM 对我来说当地时间是 4PM 联合技术公司。但请注意我们没有改变 Unixepoch公司 对象,它仍在 协调世界时 时间被设定为 8AM UTC 在里面。因此, dateInLong 28,800 (8小时x 60分钟x 60秒)。所以当你 ToDateTime() 方法被调用,它添加 28,000 秒到 UTC上午8点 时间,作为 日期时间 对象,现在是 4PM UTC 是的。

    28800个

    2017年6月1日16:00:00

    这就是为什么取决于你设定的时间 日期对象 到,你的输出 变化 时间如你所说。


    解决方案

    你需要决定使用哪个时区,并坚持这一点。一个办法是把所有的 协调世界时 转换并将所有时间设置为本地时间。

    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();
        }
    }
    

    另一个选项,将所有内容都设置为UTC,但是您必须确保 日期时间 调用的对象 ToUTC() 在UTC中定义,而不是本地。

    所以:

    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);
    

    但是…

    我看到你的代码有一个更大的问题,看看第二个代码片段。在 ForecastIORequest() 构造器,作为一个 一串 是的。在我看来,这不是一个理想的解决方案。因为当你发现困难的时候,取决于调用对象创建的时区,你的时间差将会,嗯,不同。你不可能知道。

    我宁愿储存 日期时间 按原样创建对象,读取它并在需要时计算差异,同时考虑时区。

    希望这有帮助。

        2
  •  1
  •   levelonehuman    6 年前

    DateTime.Ticks -一毫秒内有一万个滴答声。简单地 DateTime.Ticks / 10000 (一万)还有你的毫秒。

    下面是一个简单的扩展方法,可以将毫秒作为长(即int64):

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