Unix zaman damgasını DateTime'a veya tam tersine nasıl dönüştürebilirim?


754

Bu örnek kod var, ancak milisaniye / nanosaniye problemleri hakkında konuşmaya başlıyor.

Aynı soru MSDN, C # Unix çağından beri saniye .

Şimdiye kadar aldığım şey bu:

public Double CreatedEpoch
{
  get
  {
    DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime();
    TimeSpan span = (this.Created.ToLocalTime() - epoch);
    return span.TotalSeconds;
  }
  set
  {
    DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0).ToLocalTime();
    this.Created = epoch.AddSeconds(value);
  }
}

119
Yakında çıkacak olan .NET 4.6 (bu yılın ilerleyen saatlerinde yayınlanacak) buna destek vermektedir. Bkz. DateTimeOffset.FromUnixTimeSecondsVe DateTimeOffset.ToUnixTimeSecondsyöntemler. Milisaniye unix-zamanı için de yöntemler vardır.
Jeppe Stig Nielsen

Yanıtlar:


1017

İhtiyacınız olan şey:

public static DateTime UnixTimeStampToDateTime( double unixTimeStamp )
{
    // Unix timestamp is seconds past epoch
    System.DateTime dtDateTime = new DateTime(1970,1,1,0,0,0,0,System.DateTimeKind.Utc);
    dtDateTime = dtDateTime.AddSeconds( unixTimeStamp ).ToLocalTime();
    return dtDateTime;
}

Veya, Java için (zaman damgası saniyeler değil milisaniye cinsinden olduğu için farklıdır):

public static DateTime JavaTimeStampToDateTime( double javaTimeStamp )
{
    // Java timestamp is milliseconds past epoch
    System.DateTime dtDateTime = new DateTime(1970,1,1,0,0,0,0,System.DateTimeKind.Utc);
    dtDateTime = dtDateTime.AddMilliseconds( javaTimeStamp ).ToLocalTime();
    return dtDateTime;
}

5
Windows'daki zaman HAL tarafından işlenir ve yalnızca 1ms ila 15ms arasında doğruya yakındır. Daha fazla bilgi ilgilenen varsa, Windows Internals sayfa 112 civarında bulunabilir .
Jim Schubert

16
Bu cevap saniyeler içinde kesilme riskini taşır ... Bir çift kayan bir sayıdır. Argüman int / long / etc olmalıdır.
ccook

44
Bu yöntemler, çift değil uzun veya int kabul etmelidir. Ayrıca, Java zaman damgaları için 1000 ve raunta bölmeye gerek yoktur. Just dodtDateTime.AddMilliseconds(javaTimeStamp).ToLocalTime();
Justin Johnson

11
Sadece "tam tersi" mi kaçırdın? Bir DateTime'ı zaman damgasına nasıl dönüştürebiliriz?
Jonny

38
.NET Framework 4.6 ve üstü için şimdi static DateTimeOffset.FromUnixMillisecondsve vardır DateTimeOffset.ToUnixMilliseconds.
rookie1024

421

NET (V4.6) en son sürümü ekledi yerleşik Unix zaman dönüşümleri için destek. Bu, saniye veya milisaniye ile gösterilen Unix zamanına ve Unix zamanını içerir.

  • UTC'ye kadar saniye cinsinden Unix süresi DateTimeOffset:

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(1000);
  • DateTimeOffset saniye cinsinden Unix zamanı:

long unixTimeStampInSeconds = dateTimeOffset.ToUnixTimeSeconds();
  • Milisaniye cinsinden Unix süresi UTC DateTimeOffset:

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(1000000);
  • DateTimeOffset milisaniye cinsinden Unix zamanı:

long unixTimeStampInMilliseconds = dateTimeOffset.ToUnixTimeMilliseconds();

Not: Bu yöntemler UTC'ye ve UTC'den dönüşür DateTimeOffset. DateTimeTemsil almak için DateTimeOffset.UtcDateTimeveya DateTimeOffset.LocalDateTimeözelliklerini kullanmanız yeterlidir :

DateTime dateTime = dateTimeOffset.UtcDateTime;


Bu, zamanı yerel saate dönüştürmez. DateTimeOffset.FromUnixTimeSeconds () kullanırsanız UTC alırsınız.
Berend de Boer

4
@BerenddeBoer İsterseniz kullanabilirsiniz ToLocalTime.
i3arnon

1
Şu anki saati almak içinlong unixMilliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();
Dan Diplo

219

DateTime - UNIX zaman damgası:

public static double DateTimeToUnixTimestamp(DateTime dateTime)
{
    return (TimeZoneInfo.ConvertTimeToUtc(dateTime) - 
           new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc)).TotalSeconds;
}

47

Gönderen Vikipedi :

UTC mevsim değişikliği ile değişmez, ancak bir saat dilimi yargılaması yaz saatine (yaz saati) uyuyorsa yerel saat veya sivil saat değişebilir. Örneğin, Amerika Birleşik Devletleri'nin doğu kıyısındaki yerel saat, kışın UTC'nin beş saat gerisindedir, ancak gün ışığından yararlanma gözlemlenirken dört saat geridedir.

Yani bu benim kodum:

TimeSpan span = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0,DateTimeKind.Utc));
double unixTime = span.TotalSeconds;

2
ama bu bir çift döndürür, sanırım uzun bir süre için döküm gerekir?
knocte

30

Milisaniyeden daha yüksek bir hassasiyete ihtiyacınız varsa dikkatli olun!

.NET (v4.6) yöntemleri (örn. FromUnixTimeMilliseconds ) bu hassasiyeti sağlamaz.

AddSeconds ve AddMilliseconds da çiftte mikrosaniye keser.

Bu sürümler yüksek hassasiyete sahiptir:

Unix -> DateTime

public static DateTime UnixTimestampToDateTime(double unixTime)
{
    DateTime unixStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
    long unixTimeStampInTicks = (long) (unixTime * TimeSpan.TicksPerSecond);
    return new DateTime(unixStart.Ticks + unixTimeStampInTicks, System.DateTimeKind.Utc);
}

DateTime -> Unix

public static double DateTimeToUnixTimestamp(DateTime dateTime)
{
    DateTime unixStart = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
    long unixTimeStampInTicks = (dateTime.ToUniversalTime() - unixStart).Ticks;
    return (double) unixTimeStampInTicks / TimeSpan.TicksPerSecond;
}

2
Bu doğru cevap. Diğerleri, zaman damgasından dönüştürmede saat dilimini yanlış alırlar.
IamIC

DateTime-> Java için, sadece [kod] dönüş (uzun) unixTimeStampInTicks / TimeSpan.TicksPerMilliSecond; [/ kod]
En

Yani UnixTimestampToDateTime, tedarikinizde unixTimehala saniyeler içinde, değil mi?
Ngoc Pham

@NgocPham evet öyle
Felix Keil

14

Bkz. IdentityModel.EpochTimeExtensions

public static class EpochTimeExtensions
{
    /// <summary>
    /// Converts the given date value to epoch time.
    /// </summary>
    public static long ToEpochTime(this DateTime dateTime)
    {
        var date = dateTime.ToUniversalTime();
        var ticks = date.Ticks - new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).Ticks;
        var ts = ticks / TimeSpan.TicksPerSecond;
        return ts;
    }

    /// <summary>
    /// Converts the given date value to epoch time.
    /// </summary>
    public static long ToEpochTime(this DateTimeOffset dateTime)
    {
        var date = dateTime.ToUniversalTime();
        var ticks = date.Ticks - new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero).Ticks;
        var ts = ticks / TimeSpan.TicksPerSecond;
        return ts;
    }

    /// <summary>
    /// Converts the given epoch time to a <see cref="DateTime"/> with <see cref="DateTimeKind.Utc"/> kind.
    /// </summary>
    public static DateTime ToDateTimeFromEpoch(this long intDate)
    {
        var timeInTicks = intDate * TimeSpan.TicksPerSecond;
        return new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc).AddTicks(timeInTicks);
    }

    /// <summary>
    /// Converts the given epoch time to a UTC <see cref="DateTimeOffset"/>.
    /// </summary>
    public static DateTimeOffset ToDateTimeOffsetFromEpoch(this long intDate)
    {
        var timeInTicks = intDate * TimeSpan.TicksPerSecond;
        return new DateTimeOffset(1970, 1, 1, 0, 0, 0, TimeSpan.Zero).AddTicks(timeInTicks);
    }
}

Bu iyi, ama küçük bir değişiklik öneririm: "long" tipinin kullanımı "Int32" veya "int" olarak değiştirilmelidir. "Uzun", önemli bir hassasiyet olduğunu gösterir, ancak yoktur. Tüm matematik sadece 1 saniyeye kadar hassastır, bu nedenle Int32, Unix zaman damgasından beklediğinizden daha
anlamlı olacaktır

3
Bence DateTime.TicksInt64 (uzun) olmasından dolayı , kontrolsüz bir oyuncudan kaçınıyorlar.
orad

10

ScottCher'in cevabını desteklemek için, son zamanlarda kendimi hem girdi hem de milisaniye UNIX zaman damgalarının keyfi bir şekilde bir girdi veri kümesinde karıştırılması rahatsız edici senaryosunda buldum. Aşağıdaki kod bu iyi işliyor gibi görünüyor:

static readonly DateTime UnixEpoch = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
static readonly double MaxUnixSeconds = (DateTime.MaxValue - UnixEpoch).TotalSeconds;

public static DateTime UnixTimeStampToDateTime(double unixTimeStamp)
{
   return unixTimeStamp > MaxUnixSeconds
      ? UnixEpoch.AddMilliseconds(unixTimeStamp)
      : UnixEpoch.AddSeconds(unixTimeStamp);
}

1
DateTimeKind bağımsız değişkenini kullanmadığınızda dikkatli olun, çünkü oluşturulmuş DateTime bilgisayarın yerel saatinde olacaktır (kod için teşekkürler, Chris)!
Sam Grondahl

1
Dikkat - bu, milisaniye cinsinden temsil edildikleri takdirde, 11 Ocak 1978 tarihinden önceki tarihler için unix zaman damgalarında çalışmaz. 253324800 (saniye) unix tarih damgası 11.01.1978 tarihini verirken, milisaniye gösterimi 253324800000 18.07.9997 tarihini verir. Bu, veri kümeniz için işe yaramış olabilir, ancak genel bir çözüm değildir.
Øyvind

8

Unix zaman dönüşümü .NET Framework 4.6'da yenidir.

Artık tarih ve saat değerlerini .NET Framework türlerine ve Unix saatlerine veya daha kolay dönüştürebilirsiniz. Bu, örneğin bir JavaScript istemcisi ve .NET sunucusu arasında zaman değerlerini dönüştürürken gerekli olabilir. DateTimeOffset yapısına aşağıdaki API'lar eklendi :

static DateTimeOffset FromUnixTimeSeconds(long seconds)
static DateTimeOffset FromUnixTimeMilliseconds(long milliseconds)
long DateTimeOffset.ToUnixTimeSeconds()
long DateTimeOffset.ToUnixTimeMilliseconds()

Bu size yerel saat vermez, UTC alırsınız.
Berend de Boer

@BerenddeBoer Bu makul bir varsayılan değerdir. Bundan sonra istediğiniz gibi özel bir ofset uygulayabilirsiniz.
Deilan

1
@BerenddeBoer Unix zamanının ne olduğunu yanlış anlıyor. Unix zamanı gece yarısından bu yana saniyeler, 1 Ocak 1970, UTC. Nerede olduğunuz önemli değil, o dönemin değişmediği saniye sayısı. İnsan tarafından okunabilir yerel zaman göstergelerine dönüştürülmesi, olması gerektiği gibi bu evrensel gösterimden ayrıdır.
Tanktalus

5

Sadece 1/1/1970 ile yerel saat ayarlaması arasındaki dönüşümü karşılaştırarak doğru cevabı buldum;

DateTime date = new DateTime(2011, 4, 1, 12, 0, 0, 0);
DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0);
TimeSpan span = (date - epoch);
double unixTime =span.TotalSeconds;

4
var dt = DateTime.Now; 
var unixTime = ((DateTimeOffset)dt).ToUnixTimeSeconds();

// 1510396991

var dt = DateTimeOffset.FromUnixTimeSeconds(1510396991);

// [11.11.2017 10:43:11 +00: 00]


4

.Net 4.6'dan şunları yapabilirsiniz:

var dateTime = DateTimeOffset.FromUnixTimeSeconds(unixDateTime).DateTime;

3
DateTime unixEpoch = DateTime.ParseExact("1970-01-01", "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture);
DateTime convertedTime = unixEpoch.AddMilliseconds(unixTimeInMillisconds);

Tabii ki, unixEpochbir global statik yapabilir, bu yüzden projenizde sadece bir kez görünmesi gerekir AddSecondsve UNIX zamanı saniyeler içinde kullanılabilir.

Diğer yoldan gitmek için:

double unixTimeInMilliseconds = timeToConvert.Subtract(unixEpoch).TotalMilliseconds;

Int64'e kısaltın ve / veya TotalSecondsgerektiği gibi kullanın .


3

Bizim için çalışan en basit bir uzantı yazdı. Biri ararsa ...

public static class DateTimeExtensions
{
    public static DateTime FromUnixTimeStampToDateTime(this string unixTimeStamp)
    {

        return DateTimeOffset.FromUnixTimeSeconds(long.Parse(unixTimeStamp)).UtcDateTime;
    }
}


2

Unix kene 1 saniyedir (iyi hatırlıyorsam) ve .NET kene 100 nanosaniyedir.

Nanosaniye ile ilgili sorun yaşıyorsanız AddTick (10000000 * değeri) kullanmayı denemek isteyebilirsiniz.


3
Unix, dönemi 1/1 / 70'in üzerinde olan saniyedir.
ScottCher

1

Ben dönüştürmek için gerekli timeval yapı içeren (saniye, mikrosaniye) UNIX timeiçin DateTimehassas kaybetmeden ve ben sadece benimkini eklemek düşündüm işte bir cevap bulamadım:

DateTime _epochTime = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
private DateTime UnixTimeToDateTime(Timeval unixTime)
{
    return _epochTime.AddTicks(
        unixTime.Seconds * TimeSpan.TicksPerSecond +
        unixTime.Microseconds * TimeSpan.TicksPerMillisecond/1000);
}

1

DateTimeOffset kullanabilirsiniz .

Örneğin. DateTime nesnesim var

var dateTime=new DateTime();

Bunu Unix zaman damgalarına dönüştürmek istersem, aşağıdaki gibi başarılabilirim

var unixTimeSeconds= new DateTimeOffset(dateTime).ToUnixTimeSeconds()

Daha fazla bilgi için lütfen şu bağlantıyı ziyaret edin: DateTimeOffset.ToUnixTimeSeconds Yöntemi


0
public static class UnixTime
    {
        private static readonly DateTime Epoch = new DateTime(1970, 1, 1, 0, 0, 0, 0);

        public static DateTime UnixTimeToDateTime(double unixTimeStamp)
        {
            return Epoch.AddSeconds(unixTimeStamp).ToUniversalTime();
        }
    }

UnixTime.UnixTimeToDateTime (çift datetime))


-2

.NET 4.6 ve üstü için:

public static class UnixDateTime
{
    public static DateTimeOffset FromUnixTimeSeconds(long seconds)
    {
        if (seconds < -62135596800L || seconds > 253402300799L)
            throw new ArgumentOutOfRangeException("seconds", seconds, "");

        return new DateTimeOffset(seconds * 10000000L + 621355968000000000L, TimeSpan.Zero);
    }

    public static DateTimeOffset FromUnixTimeMilliseconds(long milliseconds)
    {
        if (milliseconds < -62135596800000L || milliseconds > 253402300799999L)
            throw new ArgumentOutOfRangeException("milliseconds", milliseconds, "");

        return new DateTimeOffset(milliseconds * 10000L + 621355968000000000L, TimeSpan.Zero);
    }

    public static long ToUnixTimeSeconds(this DateTimeOffset utcDateTime)
    {
        return utcDateTime.Ticks / 10000000L - 62135596800L;
    }

    public static long ToUnixTimeMilliseconds(this DateTimeOffset utcDateTime)
    {
        return utcDateTime.Ticks / 10000L - 62135596800000L;
    }

    [Test]
    public void UnixSeconds()
    {
        DateTime utcNow = DateTime.UtcNow;
        DateTimeOffset utcNowOffset = new DateTimeOffset(utcNow);

        long unixTimestampInSeconds = utcNowOffset.ToUnixTimeSeconds();

        DateTimeOffset utcNowOffsetTest = UnixDateTime.FromUnixTimeSeconds(unixTimestampInSeconds);

        Assert.AreEqual(utcNowOffset.Year, utcNowOffsetTest.Year);
        Assert.AreEqual(utcNowOffset.Month, utcNowOffsetTest.Month);
        Assert.AreEqual(utcNowOffset.Date, utcNowOffsetTest.Date);
        Assert.AreEqual(utcNowOffset.Hour, utcNowOffsetTest.Hour);
        Assert.AreEqual(utcNowOffset.Minute, utcNowOffsetTest.Minute);
        Assert.AreEqual(utcNowOffset.Second, utcNowOffsetTest.Second);
    }

    [Test]
    public void UnixMilliseconds()
    {
        DateTime utcNow = DateTime.UtcNow;
        DateTimeOffset utcNowOffset = new DateTimeOffset(utcNow);

        long unixTimestampInMilliseconds = utcNowOffset.ToUnixTimeMilliseconds();

        DateTimeOffset utcNowOffsetTest = UnixDateTime.FromUnixTimeMilliseconds(unixTimestampInMilliseconds);

        Assert.AreEqual(utcNowOffset.Year, utcNowOffsetTest.Year);
        Assert.AreEqual(utcNowOffset.Month, utcNowOffsetTest.Month);
        Assert.AreEqual(utcNowOffset.Date, utcNowOffsetTest.Date);
        Assert.AreEqual(utcNowOffset.Hour, utcNowOffsetTest.Hour);
        Assert.AreEqual(utcNowOffset.Minute, utcNowOffsetTest.Minute);
        Assert.AreEqual(utcNowOffset.Second, utcNowOffsetTest.Second);
        Assert.AreEqual(utcNowOffset.Millisecond, utcNowOffsetTest.Millisecond);
    }
}

4
Ben anlamıyorum. .NET 4.6'da BCL zaten bu yöntemlere sahiptir (örn. Yukarıdaki soruya yaptığım yorum veya diğer bazı yeni cevaplara (2015) bakın. sürümleri için bir çözüm öncesinde 4.6?
Jeppe Stig Nielsen
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.