I have had look around stackoverflow, and even looked at some of the suggested questions and none seem to answer, how do you get a unix timestamp in C#?
As of .NET 4.6, there is DateTimeOffset.ToUnixTimeSeconds
.
This is an instance method, so you are expected to call it on an instance of DateTimeOffset
. You can also cast any instance of DateTime
, though beware the timezone. To get the current timestamp:
DateTimeOffset.Now.ToUnixTimeSeconds()
To get the timestamp from a DateTime
:
DateTime foo = DateTime.Now;
long unixTime = ((DateTimeOffset)foo).ToUnixTimeSeconds();
You get a unix timestamp in C# by using DateTime.UtcNow
and subtracting the epoch time of 1970-01-01.
e.g.
Int32 unixTimestamp = (int)DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds;
DateTime.UtcNow
can be replaced with any DateTime
object that you would like to get the unix timestamp for.
There is also a field, DateTime.UnixEpoch
, which is very poorly documented by MSFT, but may be a substitute for new DateTime(1970, 1, 1)
DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).Ticks / TimeSpan.TicksPerSecond;
You can also use Ticks. I'm coding for Windows Mobile so don't have the full set of methods. TotalSeconds is not available to me.
long epochTicks = new DateTime(1970, 1, 1).Ticks;
long unixTime = ((DateTime.UtcNow.Ticks - epochTicks) / TimeSpan.TicksPerSecond);
or
TimeSpan epochTicks = new TimeSpan(new DateTime(1970, 1, 1).Ticks);
TimeSpan unixTicks = new TimeSpan(DateTime.UtcNow.Ticks) - epochTicks;
double unixTime = unixTicks.TotalSeconds;
new DateTime(1970, 1, 1)
creates a time with unspecified Kind
property. What you really want to new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)
to be truly correct
This is what I use:
public long UnixTimeNow()
{
var timeSpan = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
return (long)timeSpan.TotalSeconds;
}
Keep in mind that this method will return the time as Coordinated Univeral Time (UTC).
double
type; casting it to long will cause loss of precision.)
Truncating .TotalSeconds
is important since it's defined as the value of the current System.TimeSpan structure expressed in whole fractional seconds.
And how about an extension for DateTime
? The second one is probably more confusing that it's worth until property extensions exist.
/// <summary>
/// Converts a given DateTime into a Unix timestamp
/// </summary>
/// <param name="value">Any DateTime</param>
/// <returns>The given DateTime in Unix timestamp format</returns>
public static int ToUnixTimestamp(this DateTime value)
{
return (int)Math.Truncate((value.ToUniversalTime().Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
}
/// <summary>
/// Gets a Unix timestamp representing the current moment
/// </summary>
/// <param name="ignored">Parameter ignored</param>
/// <returns>Now expressed as a Unix timestamp</returns>
public static int UnixTimestamp(this DateTime ignored)
{
return (int)Math.Truncate((DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds);
}
Updated code from Brad with few things: You don't need Math.truncate, conversion to int or long automatically truncates the value. In my version I am using long instead of int (We will run out of 32 bit signed integers in 2038 year). Also, added timestamp parsing.
public static class DateTimeHelper
{
/// <summary>
/// Converts a given DateTime into a Unix timestamp
/// </summary>
/// <param name="value">Any DateTime</param>
/// <returns>The given DateTime in Unix timestamp format</returns>
public static long ToUnixTimestamp(this DateTime value)
{
return (long)(value.ToUniversalTime().Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
}
/// <summary>
/// Gets a Unix timestamp representing the current moment
/// </summary>
/// <param name="ignored">Parameter ignored</param>
/// <returns>Now expressed as a Unix timestamp</returns>
public static long UnixTimestamp(this DateTime ignored)
{
return (long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;
}
/// <summary>
/// Returns a local DateTime based on provided unix timestamp
/// </summary>
/// <param name="timestamp">Unix/posix timestamp</param>
/// <returns>Local datetime</returns>
public static DateTime ParseUnixTimestamp(long timestamp)
{
return (new DateTime(1970, 1, 1)).AddSeconds(timestamp).ToLocalTime();
}
}
AddMilliseconds
for the ParseUnixTimestamp(..)
method. Not AddSeconds
With .NET 6.0, using long
to avoid 2038
:
DateTime.UtcNow to UnixTime
:
long seconds = (long)DateTime.UtcNow.Subtract(DateTime.UnixEpoch).TotalSeconds;
UnixTime to DateTime.UtcNow
:
DateTime timestamp = DateTime.UnixEpoch.AddSeconds(seconds);
Fiddle: https://dotnetfiddle.net/xNhO6q
When you subtract 1970 from the current time, be aware that the timespan will most often have a non zero milliseconds field. If for some reason you are interested in the milliseconds, keep this in mind.
Here's what I did to get around this issue.
DateTime now = UtcNow();
// milliseconds Not included.
DateTime nowToTheSecond = new DateTime(now.Year,now.Month,now.Day,now.Hour,now.Minute,now.Second);
TimeSpan span = (date - new DateTime(1970, 1, 1, 0, 0, 0, 0));
Assert.That(span.Milliseconds, Is.EqualTo(0)); // passes.
This is what I use.
public class TimeStamp
{
public Int32 UnixTimeStampUTC()
{
Int32 unixTimeStamp;
DateTime currentTime = DateTime.Now;
DateTime zuluTime = currentTime.ToUniversalTime();
DateTime unixEpoch = new DateTime(1970, 1, 1);
unixTimeStamp = (Int32)(zuluTime.Subtract(unixEpoch)).TotalSeconds;
return unixTimeStamp;
}
}
Below is a 2-way extension class that supports:
Timezone localization
Input\output in seconds or milliseconds.
In OP's case, usage is:
DateTime.Now.ToUnixtime();
or
DateTime.UtcNow.ToUnixtime();
Even though a direct answer exists, I believe using a generic approach is better. Especially because it's most likely a project that needs a conversion like this, will also need these extensions anyway, so it's better to use the same tool for all.
public static class UnixtimeExtensions
{
public static readonly DateTime UNIXTIME_ZERO_POINT = new DateTime(1970, 1, 1, 0, 0,0, DateTimeKind.Utc);
/// <summary>
/// Converts a Unix timestamp (UTC timezone by definition) into a DateTime object
/// </summary>
/// <param name="value">An input of Unix timestamp in seconds or milliseconds format</param>
/// <param name="localize">should output be localized or remain in UTC timezone?</param>
/// <param name="isInMilliseconds">Is input in milliseconds or seconds?</param>
/// <returns></returns>
public static DateTime FromUnixtime(this long value, bool localize = false, bool isInMilliseconds = true)
{
DateTime result;
if (isInMilliseconds)
{
result = UNIXTIME_ZERO_POINT.AddMilliseconds(value);
}
else
{
result = UNIXTIME_ZERO_POINT.AddSeconds(value);
}
if (localize)
return result.ToLocalTime();
else
return result;
}
/// <summary>
/// Converts a DateTime object into a Unix time stamp
/// </summary>
/// <param name="value">any DateTime object as input</param>
/// <param name="isInMilliseconds">Should output be in milliseconds or seconds?</param>
/// <returns></returns>
public static long ToUnixtime(this DateTime value, bool isInMilliseconds = true)
{
if (isInMilliseconds)
{
return (long)value.ToUniversalTime().Subtract(UNIXTIME_ZERO_POINT).TotalMilliseconds;
}
else
{
return (long)value.ToUniversalTime().Subtract(UNIXTIME_ZERO_POINT).TotalSeconds;
}
}
}
This solution helped in my situation:
public class DateHelper {
public static double DateTimeToUnixTimestamp(DateTime dateTime)
{
return (TimeZoneInfo.ConvertTimeToUtc(dateTime) -
new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc)).TotalSeconds;
}
}
using helper in code:
double ret = DateHelper.DateTimeToUnixTimestamp(DateTime.Now)
I've spliced together the most elegant approaches to this utility method:
public static class Ux {
public static decimal ToUnixTimestampSecs(this DateTime date) => ToUnixTimestampTicks(date) / (decimal) TimeSpan.TicksPerSecond;
public static long ToUnixTimestampTicks(this DateTime date) => date.ToUniversalTime().Ticks - UnixEpochTicks;
private static readonly long UnixEpochTicks = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).Ticks;
}
There is a ToUnixTimeMilliseconds for DateTimeOffset in System
You can write similar method for DateTime:
public static long ToUnixTimeSeconds(this DateTime value)
{
return value.Ticks / 10000000L - 62135596800L;
}
10000000L - converting ticks to seconds
62135596800L - converting 01.01.01 to 01.01.1978
There is no problem with Utc and leaks
I used this after struggling for a while, it caters to the timezone offset as well:
public double Convert_DatTime_To_UNIXDATETIME(DateTime dt)
{
System.DateTime from_date = new DateTime(1970, 1, 1, 0, 0, 0, 0, System.DateTimeKind.Utc);
double unix_time_since = dt.Subtract(from_date).TotalMilliseconds;
TimeSpan ts_offset = TimeZoneInfo.Local.GetUtcOffset(DateTime.UtcNow);
double offset = ts_offset.TotalMilliseconds;
return unix_time_since - offset;
}
I think this would work better to get the unix timestamp from any DateTime object. I am using .net Core 3.1.
DateTime foo = DateTime.Now;
long unixTime = ((DateTimeOffset)foo ).ToUnixTimeMilliseconds();
If you have a UTC TimeStamp
as a long
in Tick
form there is an even faster shortcut for this.
/// <summary>
/// Convert Ticks to Unix Timestamp
/// </summary>
/// <param name="time"></param>
/// <returns></returns>
public static long ToUnixTimestamp(long time)
{
return (time - 621355968000000000) / TimeSpan.TicksPerMillisecond;
}
The simple code that I am using:
public static long CurrentTimestamp()
{
return (long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds * 1000);
}
This code is giving unix timestamp, total milliseconds from 1970-01-01 to now.
Success story sharing
Unix Millenium Bug
hits :)Int64
- by the time that rolls over, we'd not be using Earth years anymore for lack of an Earth.DateTime.Now.ToFileTimeUtc()
does not return the same asDateTimeOffset.Now.ToUnixTimeSeconds()
. According to MSDN, “A Windows file time is a 64-bit value that represents the number of 100-nanosecond intervals that have elapsed since 12:00 midnight, January 1, 1601 A.D. (C.E.) Coordinated Universal Time (UTC).”