Функция, которая создает метку времени в c #


101

Мне было интересно, есть ли способ создать метку времени в С # из datetime? Мне нужно значение точности в миллисекундах, которое также работает в Compact Framework (говоря, что, поскольку DateTime.ToBinary () не существует в CF).

Моя проблема в том, что я хочу сохранить это значение независимым от базы данных способом, чтобы потом можно было отсортировать его и выяснить, какое значение больше другого и т. Д.


2
Принятый ответ здесь дает хорошее решение, но если вам нужна реальная временная метка, ознакомьтесь с этим Q / A: stackoverflow.com/questions/9814060/…
inanutshellus

Ответы:


206

Я всегда использую что-то вроде следующего:

public static String GetTimestamp(this DateTime value)
{
    return value.ToString("yyyyMMddHHmmssfff");
}

Это даст вам строку типа 200905211035131468, так как строка идет от битов наивысшего порядка метки времени до самого низкого порядка. Простая сортировка строк в ваших SQL-запросах может использоваться для упорядочения по дате, если вы вставляете значения в базу данных.


5
Почему у вас 21 месяц, а у вас только 12? :)
PaulB

2
Токен для года должен быть здесь в нижнем регистре: return value.ToString ("yyyyMMddHHmmssffff");
Don Cote

1
@RobV Вопрос требует миллисекундной точности, поэтому вам нужно 3 'f в конце. Ваши 4 'f дают точность 100 микросенд.
Евгений Березовский

2
Имейте в виду, что Compact Framework не передает миллисекунды. Они всегда будут равны 0. Вам нужно изменить код и добавить что-то вроде этого: int tick = Environment.TickCount% 1000; int ms = (галочка> = MOffset)? (галочка - MOffset): (1000 - (MOffset - галочка)); мс = Math.Min (999, Math.Max ​​(0, мс));
Redwolf

44

Я считаю, что вы можете создать метку даты в стиле unix с точностью до секунды, используя следующие

//Find unix timestamp (seconds since 01/01/1970)
long ticks = DateTime.UtcNow.Ticks - DateTime.Parse("01/01/1970 00:00:00").Ticks;
ticks /= 10000000; //Convert windows ticks to seconds
timestamp = ticks.ToString();

Регулировка знаменателя позволяет выбрать уровень точности.


19

Вы можете использовать свойство DateTime.Ticks, которое является длинным и универсальным хранилищем, всегда увеличивающимся и используемым в компактной структуре. Просто убедитесь, что ваш код не используется после 31 декабря 9999 года;)


Когда вы говорите «всегда увеличивается» - нет гарантии, что два вызова DateTime.UtcNow.Ticks дадут разные значения, правда? Другими словами, вы все равно должны быть осторожны, прежде чем использовать его в качестве уникальной отметки времени.
Джон Скит

9
@Konstantinos: вы не можете избежать дублирования, если используете временные метки. Метки времени используются не для уникальных ключей, а для отметки времени. Вы сказали, что вам нужна миллисекундная точность, а у тиков точность 100 нс. Дело в том, что у вас будут дубликаты. Если вы этого не хотите, вам нужна уникальная последовательность в базе данных, которая, к сожалению, не зависит от базы данных.
Frans Bouma

3
«это реальное количество тиков, которое со временем увеличивается». Но системные часы могут идти назад - например, в конце перехода на летнее время, если вы используете местное время, или потому, что системные часы были настроены.
Джо

1
@Frans: абсолютно. Я сделал комментарий только потому, что люди должны подумать о последствиях решения, которое они выбирают. Например, я бы использовал UTC, а не местное время, чтобы хотя бы устранить проблемы с летним временем.
Джо

1
@konstantinos: хм ... в документах говорится, что он имеет точность 100 нс, поэтому действительно странно, что он не имеет такой точности, как документировано. Возможно, это действительно компактный фреймворк, а не фреймворк без ошибок,
Франс Баума,


4

когда вам нужна метка времени в секундах, вы можете использовать следующее:

var timestamp = (int)(DateTime.Now.ToUniversalTime() - new DateTime(1970, 1, 1)).TotalSeconds;

2

Если вы хотите, чтобы временные метки соответствовали фактическому реальному времени, НО также хотите, чтобы они были уникальными (для данного экземпляра приложения), вы можете использовать следующий код:

public class HiResDateTime
{
   private static long lastTimeStamp = DateTime.UtcNow.Ticks;
   public static long UtcNowTicks
   {
       get
       {
           long orig, newval;
           do
           {
               orig = lastTimeStamp;
               long now = DateTime.UtcNow.Ticks;
               newval = Math.Max(now, orig + 1);
           } while (Interlocked.CompareExchange
                        (ref lastTimeStamp, newval, orig) != orig);

           return newval;
       }
   }
}
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.