Функція, яка створює часову позначку в c #


101

Мені було цікаво, чи є спосіб створити часову позначку в c # з дати? Мені потрібно мілісекундне значення точності, яке також працює в Compact Framework (кажучи, що оскільки DateTime.ToBinary () не існує в CF).

Моя проблема полягає в тому, що я хочу зберігати це значення в agnostic базі даних, щоб я міг сортувати його пізніше і з'ясувати, яке значення більше від іншого тощо.


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");
Дон Кот

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

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

43

Я вважаю, що ви можете створити марку дати в стилі 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с. Вся справа в тому, що у вас будуть дублікати. Якщо ви не хочете, що вам потрібна унікальна послідовність у БД, яка, на жаль, не є db agnostic.
Frans Bouma

3
"це справжня кількість кліщів, яка з часом збільшується". Але системний годинник може йти назад - наприклад, наприкінці літнього часу, якщо ви використовуєте місцевий час, або тому, що системний годинник був налаштований.
Джо

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

1
@konstantinos: Хм ... документи говорять про 100-тонну точність, тому дивно, що це не така точність, як це зафіксовано. Можливо, це справді компактний каркас, це не рамки без помилок
Frans Bouma


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.