【问题标题】:Milliseconds in DateTime.Now on .NET Compact Framework always zero?.NET Compact Framework 上的 DateTime.Now 中的毫秒数始终为零?
【发布时间】:2011-02-06 01:42:08
【问题描述】:

我想为 Windows Mobile 项目上的日志设置一个时间戳。精度必须在至少一百毫秒的范围内。

但是,我对DateTime.Now 的调用返回了一个DateTime 对象,其中Millisecond 属性设置为零。 Ticks 属性也会相应地四舍五入。

如何获得更好的时间精度?
请记住,我的代码在 Compact Framework 3.5 版上运行。我使用的是 HTC touch Pro 2 设备。

根据 MusiGenesis 的回答,我创建了以下类来解决这个问题:

/// <summary>
/// A more precisely implementation of some DateTime properties on mobile devices.
/// </summary>
/// <devdoc>Tested on a HTC Touch Pro2.</devdoc>
public static class DateTimePrecisely
{
    /// <summary>
    /// Remembers the start time when this model was created.
    /// </summary>
    private static DateTime _start = DateTime.Now;
    /// <summary>
    /// Remembers the system uptime ticks when this model was created. This
    /// serves as a more precise time provider as DateTime.Now can do.
    /// </summary>
    private static int _startTick = Environment.TickCount;

    /// <summary>
    /// Gets a DateTime object that is set exactly to the current date and time on this computer, expressed as the local time.
    /// </summary>
    /// <returns></returns>
    public static DateTime Now
    {
        get
        {
            return _start.AddMilliseconds(Environment.TickCount - _startTick);
        }
    }
}

【问题讨论】:

  • 无需用“[已解决]”重新命名您的问题。您可以通过首页或搜索结果中的黄色答案计数器判断该问题是否已被接受。
  • 作为这个的来源,我应该提到这个类几乎肯定会“漂移”远离常规DateTime.Now返回的值,可能多达几秒钟(甚至更多) 在一天的过程中。您可以通过设置类的 _start 属性、等待一段时间(一天或其他时间)并将DateTime.NowDateTimePrecisely.Now 进行比较来非常简单地进行测试。
  • 如果您发现漂移量不可接受,您可以添加一个Reset 方法,获取_start_startTick 的新值,并定期调用它。这将使其与系统时钟长期同步,同时仍为您提供(据称)毫秒分辨率。或者使用ctacke的代码。
  • 是的,漂移高度依赖于 OEM 在硬件、处理器和所使用的晶体中如何处理时钟。我见过坏的(每天几乎一分钟的漂移)和好的(每天 10 毫秒)。如果没有单独的 RTC,就很难完全摆脱它。
  • @ctacke:即使System.Diagnostics.Stopwatch 在 PC 上运行(至少是我的)也有这种程度的漂移(在我的笔记本电脑上每天大约 5 秒)。

标签: c# datetime windows-mobile compact-framework timestamp


【解决方案1】:

Environment.TickCount 将返回自上次重新启动以来 Windows(或 Windows Mobile)已运行的毫秒数。

要使用它,请将这两个表单级变量添加到您的代码中:

private DateTime _start;
private int _startTick;

在表单的 Load 事件中,执行以下操作:

private void Form1_Load(object sender, EventArgs e)
{
    _start = DateTime.Now;
    _startTick = Environment.TickCount;
}

当您需要一个毫秒的 DateTime 对象时,请执行以下操作:

DateTime timeStamp = 
    _start.AddMilliseconds(Environment.TickCount - _startTick);

Environment.TickCount 是一个int,这个值将在 25 天左右后“环绕”到Int32.MinValue。如果您的设备要在不重新启动的情况下运行那么长时间,您需要添加一个小于最后读取值的Environment.TickCount 值检查,如果是,则重置_start_startTick

【讨论】:

  • +1。这成功了。太糟糕了,微软(或 HTC?)在他们的代码中没有这样做。
  • 这是 HTC 的失败,而不是微软的。由 OEM 为操作系统提供时间。
  • 请帮帮我,因为我看不到,它将如何更准确地返回时间。您将有“更多数字”,但仅此而已,因为开始时间已经不包含秒的小数部分,所以您只是添加“虚构”数字。如果在日志中使用,可以看到日志条目之间经过的时间,但不能与其他系统时间比较。
【解决方案2】:

【讨论】:

  • +1 提示。但是,这超出了我的准确性(在积极意义上)
【解决方案3】:

主要的替代方法是 System.Diagnostics.Stopwatch 类。

它在 CE 中可用,但请注意 IsHighResolution 属性。在您的设备上可能是 False,但请检查一下。

它与没有 P/Invoke 的情况一样准确。

【讨论】:

    【解决方案4】:

    在常规框架 v2.0 中,您可以使用 DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss.fff") 来获取毫秒数。更多的 f 意味着更高的精度。

    【讨论】:

    • 在 CF 中不正确。查看该问题的其他答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-11-27
    • 1970-01-01
    • 2014-08-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-09
    相关资源
    最近更新 更多