【问题标题】:C# Get specific Date in ToInt64(milliseconds)C# 获取 ToInt64 中的特定日期(毫秒)
【发布时间】:2018-07-02 17:58:43
【问题描述】:

我就是想不通……该死!请看第二个代码sn-p中的调用方法。您将看到一条注释掉的行,内容为 //_time = time.ToUTCString(); 转到第一个代码 sn-p 以查看方法 ToUTCString()。您可以看到它采用日期时间,将其转换为世界时间并减去 UnixEpoch 以获得 TotalSeconds。然后将该值转换为 Int64(),最后转换为字符串。我尝试调用方法 ToLocalString 但这也改变了日期。

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

我不想更改传入的日期。我总是传入从上午 12:00:00(或 00:00:00)开始的日期,这是我一直想要的时间。 这两种方法都会更改日期和/或时间。我输入的日期是 06/01/2017 12:00:00AM 但有时它会更改为 05/31/2017 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();
    }

【问题讨论】:

  • 如果你不想要UTC,那么不要设置DateTimeKind.UTC
  • 我需要一个类似于第一个 sn-p 中的方法,我可以在我的日期时间中发送并以相同的格式返回它。 Convert.ToInt64(毫秒).ToString()
  • 我不太确定你的问题是什么。请发布一个明确的问题,说明您到底想要达到什么目标,什么是行不通的。
  • 如果您将实际输入与预期输出和当前输出包括在内,您的问题会更清楚。我也没有读到哪些方法给您带来了问题,所有 3 种方法似乎都是相互依赖的,因此可能有自己的问题/行为(可能没有常见的错误)。
  • 这可能很有趣msdn.microsoft.com/en-us/library/… (注​​意有一个相应的版本返回毫秒,以及以相反方向操作的方法)

标签: c# datetime


【解决方案1】:

您在这里处理日期的方式存在一个根本问题,如果我将其归结为一件事,我认为问题在于 ToUniversalTime() 并没有像您认为的那样工作。

ToUniversalTime() 所做的只是简单地给出在不同时区中定义的时间的UTC 时间。例如,假设我的当地时间是UTC-7。所以如果我定义一个DateTime 对象而不指定DateTimeKind 并将值设置为2017/6/1 9:00:00,这意味着当时实际的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 对象调用该方法,该对象的DateTimeKind 设置为UTC

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

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

3600

2017 年 6 月 1 日 09:00:00

到目前为止一切顺利。

现在稍微改变一下,让我们将 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,所以请注意,这意味着9AM 我的当地时间是4PM UTC。但是请注意,我们没有更改UnixEpoch 对象,它仍然在UTC 中,并且时间设置为8AM UTC。因此,dateInLong 将是 28,800(8 小时 x 60 分钟 x 60 秒)。因此,当您的 ToDateTime() 方法被调用时,它会将 28,000 秒添加到 8AM UTC 时间,并作为 DateTime 对象返回,其中现在的时间是 4PM UTC

28800

2017 年 6 月 1 日 16:00:00

这就是为什么根据您将dateObj 设置为的时间,您的输出更改时间如您所说。


解决方案

您需要决定使用哪个时区,并坚持下去。一种选择是取消所有 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();
    }
}

另一个选项,将 EVERYTHING 设置为 UTC,但是您必须确保调用 ToUTC()DateTime 对象是在 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);

但是...

我看到你的代码存在更大的问题,查看第二个代码 sn-p。在ForecastIORequest() 构造函数中,您作为string 节省了时间。在我看来,这不是一个理想的解决方案。因为当您发现困难的方式时,根据创建调用对象的时区,您的时差将会不同。而且你无法知道是哪一个。

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

希望这会有所帮助。

【讨论】:

    【解决方案2】:

    参见DateTime.Ticks - 毫秒内有 10,000 个滴答声。只需使用DateTime.Ticks / 10000(一万),您就有了毫秒数。

    这是一个简单的扩展方法,可以将毫秒作为 long(即 Int64):

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

    【讨论】:

      猜你喜欢
      • 2021-05-31
      • 1970-01-01
      • 2018-05-18
      • 2014-10-12
      • 1970-01-01
      • 2012-11-20
      • 2017-02-14
      • 1970-01-01
      • 2021-12-21
      相关资源
      最近更新 更多