969

There is this example code, but then it starts talking about millisecond / nanosecond problems.

The same question is on MSDN, Seconds since the Unix epoch in C#.

This is what I've got so far:

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);
  }
}
Callum Watkins
  • 2,844
  • 4
  • 29
  • 49
Mark Ingram
  • 71,849
  • 51
  • 176
  • 230
  • 173
    The upcoming **.NET 4.6** (to be release later in this year) introduces support for this. See [`DateTimeOffset.FromUnixTimeSeconds`](https://msdn.microsoft.com/en-us/library/system.datetimeoffset.fromunixtimeseconds.aspx) and [`DateTimeOffset.ToUnixTimeSeconds`](https://msdn.microsoft.com/en-us/library/system.datetimeoffset.tounixtimeseconds.aspx) methods. There are methods for millisecond unix-time as well. – Jeppe Stig Nielsen May 05 '15 at 09:29
  • 7
    Another addition was `DateTime.UnixEpoch`. Unless you need a `DateTimeOffset` instead of a `DateTime`, I think `DateTime.UnixEpoch.AddMilliseconds(...)` has slightly better readability than `DateTimeOffset.FromUnixTimeMilliseconds(...).UtcDateTime`. – M-Pixel Feb 13 '22 at 06:39

23 Answers23

1248

Here's what you need:

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

Or, for Java (which is different because the timestamp is in milliseconds, not seconds):

public static DateTime JavaTimeStampToDateTime( double javaTimeStamp )
{
    // Java timestamp is milliseconds past epoch
    DateTime dateTime = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
    dateTime = dateTime.AddMilliseconds( javaTimeStamp ).ToLocalTime();
    return dateTime;
}
live2
  • 3,771
  • 2
  • 37
  • 46
ScottCher
  • 14,651
  • 6
  • 26
  • 25
  • 3
    AddSeconds doesn't seem to behave very well for values lesser than 0.1 milliseconds (iirc) – Luk Nov 03 '08 at 17:32
  • @Luk yes, a number of methods of DateTime/TimeSpan are [inexplicably sub-millisecond impaired](http://stackoverflow.com/questions/4672359/why-does-timespan-fromsecondsdouble-round-to-milliseconds)... – Roman Starkov Apr 15 '11 at 20:36
  • 6
    Time in Windows is handled by HAL and only close-to-accurate within 1ms to 15ms. More info is available in [Windows Internals](http://shop.oreilly.com/product/0790145305930.do) around page 112, if anyone is interested. – Joseph Yaduvanshi Apr 13 '12 at 14:59
  • 30
    This answer risks truncating the seconds... A double is a floating number. The argument should be int/long/etc. – ccook Mar 04 '13 at 14:59
  • 52
    These methods should accept a long or int, not a double. Also, for the Java time stamps, there is no need to divide by 1000 and round. Just do `dtDateTime.AddMilliseconds(javaTimeStamp).ToLocalTime();` – Justin Johnson Feb 21 '14 at 21:20
  • 11
    Did you just miss the "vice versa"? How do we convert a DateTime to a timestamp? – Jonny Dec 08 '14 at 08:31
  • 58
    For the .NET Framework 4.6 and above there is now `static DateTimeOffset.FromUnixMilliseconds` and `DateTimeOffset.ToUnixMilliseconds`. – rookie1024 May 18 '16 at 02:49
  • System.DateTime dtDateTime = new DateTime.MinValue; should be sufficient. – needfulthing Aug 22 '18 at 14:34
  • A better way to do the math without floating point errors is this: `unixEpoch.AddTicks( TimeSpan.TicksPerSecond * seconds )` – Soonts Sep 26 '19 at 23:19
  • 1
    _"for Java (which is different because the timestamp is in milliseconds, not seconds)"_ This doesn't make any sense. Whether the timestamp is in seconds or milliseconds depends on where the timestamp came from. I'm calling various HTTP/JSON APIs in my C# app, several of which use unix-style timestamps; some of them return ms timestamps, others return seconds timestamps. – M-Pixel Feb 13 '22 at 06:33
621

The latest version of .NET (v4.6) has added built-in support for Unix time conversions. That includes both to and from Unix time represented by either seconds or milliseconds.

  • Unix time in seconds to UTC DateTimeOffset:

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeSeconds(1000);
  • DateTimeOffset to Unix time in seconds:

long unixTimeStampInSeconds = dateTimeOffset.ToUnixTimeSeconds();
  • Unix time in milliseconds to UTC DateTimeOffset:

DateTimeOffset dateTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(1000000);
  • DateTimeOffset to Unix time in milliseconds:

long unixTimeStampInMilliseconds = dateTimeOffset.ToUnixTimeMilliseconds();

Note: These methods convert to and from a UTC DateTimeOffset. To get a DateTime representation simply use the DateTimeOffset.UtcDateTime or DateTimeOffset.LocalDateTime properties:

DateTime dateTime = dateTimeOffset.UtcDateTime;
samlh
  • 3
  • 2
i3arnon
  • 113,022
  • 33
  • 324
  • 344
  • 1
    https://learn.microsoft.com/en-us/dotnet/api/system.datetimeoffset.fromunixtimeseconds?view=netframework-4.6.2#System_DateTimeOffset_FromUnixTimeSeconds_System_Int64_ – yedevtxt Jul 12 '17 at 16:35
  • 1
    This does not convert time to local time. You get UTC if you use DateTimeOffset.FromUnixTimeSeconds(). – Berend de Boer Aug 27 '17 at 23:56
  • 6
    @BerenddeBoer You can use `ToLocalTime` if you want. – i3arnon Aug 28 '17 at 17:11
  • 6
    To get current time you can use `long unixMilliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();` – Dan Diplo Apr 04 '19 at 09:54
  • 1
    An absolute quality answer. – user1514042 Jul 21 '20 at 15:12
  • var DateTime1 = DateTimeOffset.FromUnixTimeMilliseconds(Timestamp).LocalDateTime and var DateTime2 = DateTimeOffset.FromUnixTimeMilliseconds(Timestamp).UtcDateTime.ToLocalTime() same result – Ricko.. Dec 01 '22 at 16:26
226

DateTime to UNIX timestamp:

public static double DateTimeToUnixTimestamp(DateTime dateTime)
{
    return (TimeZoneInfo.ConvertTimeToUtc(dateTime) - 
           new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc)).TotalSeconds;
}
Nasreddine
  • 36,610
  • 17
  • 75
  • 94
Dmitry Fedorkov
  • 4,301
  • 1
  • 21
  • 30
49

From Wikipedia:

UTC does not change with a change of seasons, but local time or civil time may change if a time zone jurisdiction observes daylight saving time (summer time). For example, local time on the east coast of the United States is five hours behind UTC during winter, but four hours behind while daylight saving is observed there.

So this is my code:

TimeSpan span = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0, 0,DateTimeKind.Utc));
double unixTime = span.TotalSeconds;
Pang
  • 9,564
  • 146
  • 81
  • 122
gl051
  • 571
  • 4
  • 8
47

You can use DateTimeOffset.

For example. I have a DateTime object

var dateTime1 = DateTime.Now;

If I want to convert it to the Unix time stamps, it can be achieved as follows

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

If you want convert unix timeStamp to normal DateTime, you can use this code piece:

var dateTime2 = DateTimeOffset.FromUnixTimeSeconds(unixTimeSeconds).LocalDateTime;

or

var dateTime2 = DateTimeOffset.FromUnixTimeSeconds(unixTimeSeconds).UtcDateTime;

For more information please visit this link :

DateTimeOffset.ToUnixTimeSeconds Method,
DateTimeOffset.FromUnixTimeSeconds

nzrytmn
  • 6,193
  • 1
  • 41
  • 38
Ramil Aliyev 007
  • 4,437
  • 2
  • 31
  • 47
39

Be careful, if you need precision higher than milliseconds!

.NET (v4.6) methods (e.g. FromUnixTimeMilliseconds) don't provide this precision.

AddSeconds and AddMilliseconds also cut off the microseconds in the double.

These versions have high precision:

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;
}
Felix Keil
  • 2,344
  • 1
  • 25
  • 27
  • 2
    This is the correct answer. The others get the time zone incorrect on the convert back from timestamp. – IamIC Jun 20 '17 at 10:10
  • 1
    for DateTime->Java, just [code] return (long) unixTimeStampInTicks / TimeSpan.TicksPerMilliSecond; [/code] – Max Feb 17 '18 at 18:07
17

See 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);
    }
}
orad
  • 15,272
  • 23
  • 77
  • 113
  • This is good, but I'd suggest a small change: Use of type "long" should be changed to "Int32" or "int". "Long" implies there is significant precision, but there isn't. All of the math is only precise to 1 second so Int32 would be more suggestive of what you'd expect from a Unix timestamp – JamesHoux Dec 14 '18 at 02:47
  • 3
    I think it's due to `DateTime.Ticks` being Int64 (long), so they're avoiding an extra unchecked cast. – orad Dec 14 '18 at 20:42
14

In C# 8.0 (.NET Core 2.1) it is a simple one liner:

DateTime.UnixEpoch.AddSeconds(unixTimeInSeconds)
Brendan Sluke
  • 857
  • 10
  • 11
12

Unix epoch is now part of DateTime class. Converting millis to DateTime is as easy as

DateTime.UnixEpoch.AddMilliseconds(millis)
11

To supplement ScottCher's answer, I recently found myself in the annoying scenario of having both seconds and milliseconds UNIX timestamps arbitrarily mixed together in an input data set. The following code seems to handle this well:

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);
}
Chris Thoman
  • 331
  • 3
  • 3
  • 1
    Be careful when not using the DateTimeKind argument, since the constructed DateTime will be in the computer's local time (thanks for the code, Chris)! – Sam Grondahl Sep 16 '13 at 22:40
  • 2
    Beware - this will not work for unix timestamps for dates prior to the 11th of January 1978 if they're represented in milliseconds. A unix datestamp of 253324800 (seconds) gives the correct date of 11.01.1978, whereas the millisecond representation 253324800000 gives a date of 18.07.9997. This may have worked for your data set, but it's not a general solution. – Øyvind May 17 '18 at 07:24
11

Unix time conversion is new in .NET Framework 4.6.

You can now more easily convert date and time values to or from .NET Framework types and Unix time. This can be necessary, for example, when converting time values between a JavaScript client and .NET server. The following APIs have been added to the DateTimeOffset structure:

static DateTimeOffset FromUnixTimeSeconds(long seconds)
static DateTimeOffset FromUnixTimeMilliseconds(long milliseconds)
long DateTimeOffset.ToUnixTimeSeconds()
long DateTimeOffset.ToUnixTimeMilliseconds()
Elanis
  • 184
  • 3
  • 12
Fred
  • 12,086
  • 7
  • 60
  • 83
  • This does not give you local time, you get UTC. – Berend de Boer Aug 27 '17 at 23:57
  • @BerenddeBoer That's a reasonable default. You may apply a custom offset after that as you want. – Deilan Nov 21 '17 at 13:04
  • 1
    @BerenddeBoer That misunderstands what unix time is. Unix time is seconds since midnight, Jan 1, 1970, UTC. Doesn't matter where you are, the number of seconds since that epoch doesn't change. Converting it to human readable local time displays are separate from this universal representation, as it should be. – Tanktalus Sep 11 '18 at 17:18
9
var dt = DateTime.Now; 
var unixTime = ((DateTimeOffset)dt).ToUnixTimeSeconds();

// 1510396991

var dt = DateTimeOffset.FromUnixTimeSeconds(1510396991);

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

mesut
  • 2,099
  • 3
  • 23
  • 35
7

From .net 4.6, you can do this:

var dateTime = DateTimeOffset.FromUnixTimeSeconds(unixDateTime).DateTime;
Yang Zhang
  • 4,540
  • 4
  • 37
  • 34
7

Written a simplest extension that works for us. If anyone looks for it...

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

        return DateTimeOffset.FromUnixTimeSeconds(long.Parse(unixTimeStamp)).UtcDateTime;
    }
}
Riyaz Hameed
  • 1,087
  • 12
  • 10
6

I found the right answer just by comparing the conversion to 1/1/1970 w/o the local time adjustment;

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;
CyberFox
  • 780
  • 6
  • 24
n8CodeGuru
  • 413
  • 1
  • 6
  • 13
6
System.DateTimeOffset.Now.ToUnixTimeSeconds()
AMieres
  • 4,944
  • 1
  • 14
  • 19
4
DateTime unixEpoch = DateTime.ParseExact("1970-01-01", "yyyy-MM-dd", System.Globalization.CultureInfo.InvariantCulture);
DateTime convertedTime = unixEpoch.AddMilliseconds(unixTimeInMillisconds);

Of course, one can make unixEpoch a global static, so it only needs to appear once in your project, and one can use AddSeconds if the UNIX time is in seconds.

To go the other way:

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

Truncate to Int64 and/or use TotalSeconds as needed.

Hot Licks
  • 47,103
  • 17
  • 93
  • 151
3

A Unix tick is 1 second (if I remember well), and a .NET tick is 100 nanoseconds.

If you've been encountering problems with nanoseconds, you might want to try using AddTick(10000000 * value).

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Luk
  • 5,371
  • 4
  • 40
  • 55
1

I needed to convert a timeval struct (seconds, microseconds) containing UNIX time to DateTime without losing precision and haven't found an answer here so I thought I just might add mine:

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);
}
Elanis
  • 184
  • 3
  • 12
i3arnon
  • 113,022
  • 33
  • 324
  • 344
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();
        }
    }

you can call UnixTime.UnixTimeToDateTime(double datetime))

madan
  • 81
  • 6
0

For a while in .NET the DateTimeOffset class has had a method called FromUnixTimeMilliseconds which does do what you're looking for. This accepts the Unix time in milliseconds that have elapsed since 1970-01-01T00:00:00Z (January 1, 1970, at 12:00 AM UTC).

To use it, first convert the milliseconds to a DateTimeOffset:

long millisecs = 1677514053797;  // replace this with the Unix time you need to convert
DateTimeOffset unixTimeOffset = DateTimeOffset.FromUnixTimeMilliseconds(millisecs);

Note: the offset has an Offset property which will be set to TimeSpan.Zero, which represents UTC, it is not timezone adjusted.

Next create a DateTime instance from the offset:

DateTime dt = new DateTime(unixTimeOffset.Ticks, DateTimeKind.Utc);

To convert it back from DateTime to Unix millisecond time:

DateTimeOffset backToUnixTimeOffset = new DateTimeOffset(dt, TimeSpan.Zero);
long backToMillisecs = backToUnixTimeOffset.ToUnixTimeMilliseconds();

The documentation for it is here: https://learn.microsoft.com/en-us/dotnet/api/system.datetimeoffset.fromunixtimemilliseconds?view=net-7.0 and here: https://learn.microsoft.com/en-us/dotnet/api/system.datetimeoffset.tounixtimemilliseconds?view=net-7.0#system-datetimeoffset-tounixtimemilliseconds.

Hope this helps.

0

With .NET 6.0, and using long to avoid the 2038 problem:

From DateTime.UtcNow to UnixTime

long seconds = (long)DateTime.UtcNow.Subtract(DateTime.UnixEpoch).TotalSeconds;

seconds will contains the seconds since 01/01/1970 (UnixTime)

From UnixTime to DateTime.UtcNow

DateTime timestamp = DateTime.UnixEpoch.AddSeconds(seconds);

Fiddle: https://dotnetfiddle.net/xNhO6q

Leandro Bardelli
  • 10,561
  • 15
  • 79
  • 116
-2

For .NET 4.6 and later:

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);
    }
}
Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
superlogical
  • 14,332
  • 9
  • 66
  • 76
  • 4
    I do not understand. In .NET 4.6, the BCL already has those methods (see e.g. my comment to the question above, or some of the other new answers (2015). So what should the point be in writing them again? Did you mean that your answer was a solution for versions _prior_ to 4.6? – Jeppe Stig Nielsen Feb 19 '16 at 10:32