ChatGPT解决这个技术问题 Extra ChatGPT

How can I convert a Unix timestamp to DateTime and vice versa?

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);
  }
}
The upcoming .NET 4.6 (to be release later in this year) introduces support for this. See DateTimeOffset.FromUnixTimeSeconds and DateTimeOffset.ToUnixTimeSeconds methods. There are methods for millisecond unix-time as well.
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.

l
live2

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;
}

Time in Windows is handled by HAL and only close-to-accurate within 1ms to 15ms. More info is available in Windows Internals around page 112, if anyone is interested.
This answer risks truncating the seconds... A double is a floating number. The argument should be int/long/etc.
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();
Did you just miss the "vice versa"? How do we convert a DateTime to a timestamp?
For the .NET Framework 4.6 and above there is now static DateTimeOffset.FromUnixMilliseconds and DateTimeOffset.ToUnixMilliseconds.
s
samlh

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;

This does not convert time to local time. You get UTC if you use DateTimeOffset.FromUnixTimeSeconds().
@BerenddeBoer You can use ToLocalTime if you want.
To get current time you can use long unixMilliseconds = DateTimeOffset.Now.ToUnixTimeMilliseconds();
An absolute quality answer.
N
Nasreddine

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;
}

I get different results if I run from the cloud of from local host. That makes sense?
P
Pang

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;

but this returns a double, I guess one needs to cast to long?
F
Felix Keil

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;
}

This is the correct answer. The others get the time zone incorrect on the convert back from timestamp.
for DateTime->Java, just [code] return (long) unixTimeStampInTicks / TimeSpan.TicksPerMilliSecond; [/code]
n
nzrytmn

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


if you literally want Now as a UNIX time you can use DateTimeOffset.UtcNow.ToUnixTimeSeconds()
o
orad

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);
    }
}

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
I think it's due to DateTime.Ticks being Int64 (long), so they're avoiding an extra unchecked cast.
C
Chris Thoman

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);
}

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)!
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.
E
Elanis

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

This does not give you local time, you get UTC.
@BerenddeBoer That's a reasonable default. You may apply a custom offset after that as you want.
@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.
N
Nilufar Makhmudova

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

DateTime.UnixEpoch.AddMilliseconds(millis)

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

// 1510396991

var dt = DateTimeOffset.FromUnixTimeSeconds(1510396991);

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


B
Brendan Sluke

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

DateTime.UnixEpoch.AddSeconds(unixTimeInSeconds)

C
CyberFox

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;

Y
Yang Zhang

From .net 4.6, you can do this:

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

R
Riyaz Hameed

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;
    }
}

A
AMieres
System.DateTimeOffset.Now.ToUnixTimeSeconds()

H
Hot Licks
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.


P
Peter Mortensen

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).


Unix is seconds past epoch - which is 1/1/70.
E
Elanis

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);
}

m
madan
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))


P
Peter Mortensen

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);
    }
}

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?