C # 'da zaman damgası oluşturan işlev


101

Merak ediyordum, c # 'da bir tarih saatinden bir zaman damgası oluşturmanın bir yolu var mı? Compact Framework'te de çalışan bir milisaniye hassasiyet değerine ihtiyacım var (CF'de DateTime.ToBinary () bulunmadığından beri).

Benim sorunum, bu değeri bir veritabanında agnostik bir şekilde saklamak istemem, böylece daha sonra sıralayabilir ve hangi değerin diğerinden daha büyük olduğunu öğrenebilirim.


2
Burada kabul edilen cevap güzel bir çözüm sunar, ancak gerçek bir zaman damgası istiyorsanız, şu Soru /
Cevap'a bakın

Yanıtlar:


206

Her zaman aşağıdaki gibi bir şey kullanırım:

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

Bu size 200905211035131468 gibi bir dize verecektir, çünkü dize, zaman damgasının en yüksek dereceli bitlerinden en düşük sıraya doğru ilerlerken, SQL sorgularınızdaki basit dize sıralaması, bir veritabanına değerler yapıştırıyorsanız, tarihe göre sıralamak için kullanılabilir.


5
Nasıl olur da 21 ay alırsın ve sadece 12 alırsın? :)
PaulB

2
Yıl belirteci burada küçük harf olmalıdır: return value.ToString ("yyyyMMddHHmmssffff");
Don Cote

1
@RobV Soru milisaniye hassasiyetini soruyor, bu yüzden sonunda 3 'f'ye ihtiyacınız var. 4 'f'leriniz 100 mikro uç hassasiyeti verir.
Evgeniy Berezovsky

2
Compact Framework milisaniyeleri transfer etmediğini unutmayın. Her zaman 0 olacaktır. Kodu değiştirmeli ve buna benzer bir şey eklemelisiniz: int tick = Environment.TickCount% 1000; int ms = (işaret> = MOffset)? (tik - MOffset): (1000 - (Mofset - tik)); ms = Matematik.Min (999, Matematik.Maks (0, ms));
Redwolf

44

Aşağıdakileri kullanarak bir saniyeye kadar doğru bir unix stili veri damgası oluşturabileceğinizi düşünüyorum

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

Paydanın ayarlanması, hassasiyet seviyenizi seçmenize olanak sağlar


19

Uzun ve evrensel bir depolanabilir olan, her zaman artan ve kompakt çerçevede kullanılabilir olan DateTime.Ticks özelliğini kullanabilirsiniz. Kodunuzun 31 Aralık 9999'dan sonra kullanılmadığından emin olun;)


"Her zaman artan" dediğinizde - DateTime.UtcNow.Ticks'e yapılan iki çağrının farklı değerler vereceğinin garantisi yoktur, değil mi? Başka bir deyişle, onu benzersiz bir zaman damgası olarak kullanmadan önce yine de biraz dikkatli olmanız gerekir.
Jon Skeet

9
@Konstantinos: Zaman damgaları kullanırsanız kopyaları önleyemezsiniz. Zaman damgaları benzersiz anahtarlar için değil, bir zamanı işaretlemek için kullanılır. Milisaniye hassasiyete ihtiyacınız olduğunu söylediniz ve keneler 100ns hassasiyete sahiptir. Mesele şu ki, kopyalarınız olacak. Eğer DB'de benzersiz bir diziye ihtiyacınız olmasını istemiyorsanız, bu maalesef db agnostik değildir.
Frans Bouma

3
"zamanla artan gerçek bir tıklama sayısıdır". Ancak sistem saati geriye gidebilir - örneğin, yerel saati kullanıyorsanız veya sistem saati ayarlandığı için gün ışığından yararlanma saatinin sonunda.
Joe

1
@Frans: kesinlikle. Ben sadece yorum yaptım çünkü insanlar seçtikleri çözümün sonuçlarını düşünmeli. Örneğin, en azından DST'nin sorunlarını ortadan kaldırmak için yerel saat yerine UTC'yi kullanırdım.
Joe

1
@konstantinos: hmm ... Dokümanlar 100ns hassasiyete sahip olduğunu söylüyor, bu yüzden gerçekten de belgelendiği kadar hassas olmaması garip. Belki de kompakt çerçevedir, hatasız bir çerçeve değildir
Frans Bouma


4

Saniyeler içinde bir zaman damgasına ihtiyacınız olduğunda, aşağıdakileri kullanabilirsiniz:

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

2

Gerçek gerçek zamanlara karşılık gelen zaman damgalarını istiyorsanız ANCAK bunların benzersiz olmasını istiyorsanız (belirli bir uygulama örneği için), aşağıdaki kodu kullanabilirsiniz:

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;
       }
   }
}
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.