Как сохранить точность, используя DateTime.Now.Ticks в C # - PullRequest
7 голосов
/ 23 апреля 2010

Я знаю, что когда я использую DateTime.Now.Ticks в C #, он возвращает длинное значение, но мне нужно сохранить его в переменной int, и я не понимаю, могу ли я поддерживать эту точность или нет.На данный момент у меня просто есть приведение

int timeStampValue = (int)DateTime.Now.Ticks;

Это ограничение проекта, поэтому я понимаю, что теряется куча точности.Я думаю, я просто не мог придумать другой способ сделать временную метку, хранящуюся в int, которую я мог бы затем сравнить с другими временными метками.очень цениться.

Все ответы были иллюстративными.Я на самом деле закончил тем, что настроил процесс, включающий счетчики, где при использовании элемента его счетчик устанавливается на «0», а все остальные счетчики увеличиваются на 1. Тогда какой бы самый высокий счетчик не использовался следующим элементом.

Ответы [ 5 ]

13 голосов
/ 23 апреля 2010

DateTime.Now не совсем так точно.

http://blogs.msdn.com/ericlippert/archive/2010/04/08/precision-and-accuracy-of-datetime.aspx

С учетом сказанного, если вы приведете значение к меньшему типу, по умолчанию вы можете потерять данные в любой ситуации.

Рассмотрим этот вывод:

int.MaxValue:       2147483647
DateTime.Now.Ticks: 634075598514933010

Как преобразовать это в int реалистичный вариант?

11 голосов
/ 23 апреля 2010

Вам нужны все самые значимые биты? (например, в каком году)

Вам нужны все младшие биты? (например, точность ниже наносекунды)

Как долго нужно измерять интервал?

Если вам нужна только точность в миллисекундах, почему бы не потерять младшие значащие биты

int timeStamp = (int)(DateTime.Now.Ticks >> 10) // lose smallest 10 bits

1010 * редактировать * ОП хочет хранить время недавно использованных элементов: если это выбор пользователя для одного пользователя, вы, вероятно, не хотите ничего короче секунды! поскольку существует 10 ^ 7 тиков в секунду, в длинном значении есть log (10 ^ 7) / log (2) = 23 лишних бита! Так сколько места вам нужно? Ну, ваши значения должны указывать год, месяц, день, час, минуту и ​​секунду; В году около 32 миллионов секунд = около 24 бит. добавьте 3 бита, если хотите сохранить последние 10 лет. Так что легко впишется в int32. Я бы предложил int timeStamp = (int)(DateTime.Now.Ticks >>23) // retain bits 23 to 55

2 голосов
/ 23 апреля 2010

Больше ударов, чем чего бы то ни было ... Если вы не устали использовать ints для хранения DateTime и поддержания точности, вы можете определить свою собственную структуру, содержащую два int, каждая из которых содержит 4 байта, и DateTime, который разделяет эти значения. байт.

public class Program
{
    public static void Main(string[] args)
    {
        DateTime now = DateTime.Now;
        var myDate = new Int32BackedDate(now.Ticks);

        Console.WriteLine(now);
        Console.WriteLine(myDate.Date);
    }
}

[StructLayout(LayoutKind.Explicit, Size = 8)]
public struct Int32BackedDate
{
    [FieldOffset(4)]
    private readonly int _high;

    [FieldOffset(0)]
    private readonly int _low;

    [FieldOffset(0)]
    private readonly DateTime _date;

    public DateTime Date { get { return _date; } }

    public Int32BackedDate(long ticks)
    {
        _date = default(DateTime);
        byte[] bytes = BitConverter.GetBytes(ticks);
        _low = BitConverter.ToInt32(bytes, 0);
        _high = BitConverter.ToInt32(bytes, 4);
    }
}
2 голосов
/ 23 апреля 2010

Если разрешение в миллисекундах достаточно хорошее, вы можете сохранить смещения из некоторого базового DataTime в поле int, а затем восстановить полное значение DateTime, когда вам это нужно. Миллисекунды, хранящиеся в 32-разрядном целом числе, позволят вашему приложению работать в течение 49 дней до его переноса. Вот простой вспомогательный класс, который вы можете использовать:

public class TimeOffsetManager
{
    public TimeOffsetManager()
    {
        InitialDateTime = DateTime.Now;
    }

    public DateTime InitialDateTime { get; private set; }

    public int GetOffset()
    {
        TimeSpan elapsed = DateTime.Now - InitialDateTime;
        return (int)Math.Round(elapsed.TotalMilliseconds);
    }

    public DateTime OffsetToDateTime(int offset)
    {
        return InitialDateTime + TimeSpan.FromMilliseconds(offset);
    }
}

Может использоваться как:

public static void Method()
{
    var offsetManager = new TimeOffsetManager();

    int offset = offsetManager.GetOffset();

    // ...

    DateTime realTime = offsetManager.OffsetToDateTime(offset);
}
1 голос
/ 23 апреля 2010

На мой комментарий выше. Какое именно ограничение? Если ограничением является то, что вы не можете хранить данные в 64-битной переменной, как насчет того, чтобы сделать что-то вроде

uint tsLow = (uint)DateTime.Now.Ticks;
uint tsHigh = (uint)(DateTime.Now.Ticks >> 32);

Теперь вы можете хранить как tsLow, так и tsHigh для ваших внешних данных. Вы также можете реализовать специальные функции, которые могут вычислять значения, используя два отдельных 32-битных числа, чтобы выполнить свою собственную 64-битную математику.

Это действительно зависит от ваших реальных ограничений. Знание этого поможет предложить лучшие решения.

...