Cómo obtener la marca de tiempo de Unix en C #

Respuestas:

597

Obtiene una marca de tiempo de Unix en C # al usar DateTime.UtcNowy restar el tiempo de la época de 1970-01-01.

p.ej

Int32 unixTimestamp = (Int32)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1))).TotalSeconds;

DateTime.UtcNowse puede reemplazar con cualquier DateTimeobjeto para el que desea obtener la marca de tiempo de Unix.

También hay un campo, DateTime.UnixEpochque está muy poco documentado por MSFT, pero puede ser un sustituto denew DateTime(1970, 1, 1)

bizzehdee
fuente
28
Comentando en nombre de @wdhough. "Esta respuesta tiene una limitación con el límite de Int32 que es, creo, 2,147,483,647. De acuerdo con onlineconversion.com/unix_time.htm esto equivale a un tiempo de martes, 19 de enero de 2038 03:14:07 GMT supongo que cualquier tipo de número alternativo , doble, largo, etc. en última instancia también tendrá un límite, pero pensé que vale la pena mencionarlo. Elegí mucho aquí porque quería un número entero. Espero que esto ayude "
IsmailS
11
La marca de tiempo de Unix es tradicionalmente un número entero de 32 bits y tiene un rango de '1970-01-01 00:00:01' UTC a '2038-01-19 03:14:07' UTC.
the_nuts
89
Es una locura que la conversión de hora UNIX no esté en la biblioteca estándar como parte de DateTime.
xingyu
77
O usando aritmética de enteros:DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).Ticks / TimeSpan.TicksPerSecond;
Anton Petrov
2
¿La fecha y hora restada no necesita ser UTC?
jjxtra
573

A partir de .NET 4.6, existe DateTimeOffset.ToUnixTimeSeconds().


Este es un método de instancia, por lo que se espera que lo llame en una instancia de DateTimeOffset. También puede emitir cualquier instancia de DateTime, aunque tenga cuidado con la zona horaria .

Para obtener la marca de tiempo actual:

DateTimeOffset.UtcNow.ToUnixTimeSeconds()

Para obtener la marca de tiempo de un DateTime:

DateTime foo = DateTime.UtcNow;
long unixTime = ((DateTimeOffset)foo).ToUnixTimeSeconds();
Beto
fuente
126
Bueno.
Ya es
35
@MattBorja Afortunadamente, devuelve un Int64: para cuando se da la vuelta, ya no estaríamos usando los años de la Tierra por falta de una Tierra.
Bob
24
Para cualquiera que se pregunte, puede obtener la marca de tiempo actual conDateTimeOffset.Now.ToUnixTimeSeconds()
kR105
8
@bizzehdee, juego de palabras previsto?
2017
55
Puede obtener la marca unixtimes UTC con: DateTimeOffset.UtcNow.ToUnixTimeSeconds ()
Yair Levi el
39

También puedes usar garrapatas. Estoy codificando para Windows Mobile, así que no tengo el conjunto completo de métodos. TotalSeconds no está disponible para mí.

long epochTicks = new DateTime(1970, 1, 1).Ticks;
long unixTime = ((DateTime.UtcNow.Ticks - epochTicks) / TimeSpan.TicksPerSecond);

o

TimeSpan epochTicks = new TimeSpan(new DateTime(1970, 1, 1).Ticks);
TimeSpan unixTicks = new TimeSpan(DateTime.UtcNow.Ticks) - epochTicks;
double unixTime = unixTicks.TotalSeconds;
Dave Hindle
fuente
1
Error para la segunda solución: no se puede convertir el tipo de origen 'doble' al tipo de destino 'largo'.
Pixar
@Pixar: La segunda muestra está arreglada
JBert
55
new DateTime(1970, 1, 1)crea un tiempo con Kindpropiedad no especificada . Lo que realmente quieres que new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)sea ​​realmente correcto
desautorizado el
Desde .NET Core 2.1 Puede usar DateTime.UnixEpoch en lugar del nuevo DateTime (1970, 1, 1) vea docs.microsoft.com/en-us/dotnet/api/…
Jaa H
27

Esto es lo que uso:

public long UnixTimeNow()
{
    var timeSpan = (DateTime.UtcNow - new DateTime(1970, 1, 1, 0, 0, 0));
    return (long)timeSpan.TotalSeconds;
}

Tenga en cuenta que este método devolverá la hora como hora universal coordinada (UTC).

Bartłomiej Mucha
fuente
(TotalSeconds tiene doubletipo; si lo hace demasiado largo, perderá precisión.)
franco del
Tienes razón, pero no tenemos que preocuparnos por eso durante varios miles de años :)
Bartłomiej Mucha
21

Truncar .TotalSecondses importante ya que se define comothe value of the current System.TimeSpan structure expressed in whole fractional seconds.

¿Y qué tal una extensión para DateTime? El segundo es probablemente más confuso que vale la pena hasta que existan extensiones de propiedad.

/// <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);
}
Puntilla
fuente
2
El método de extensión es claramente la forma de hacer esto de forma ordenada. Esta es una respuesta excelente y madura, y no entiendo por qué tiene tan pocos votos. Estoy bastante seguro de que Robba es correcto: convertir la salida como (int) trunca automáticamente el resultado. (Literalmente ignorando la parte decimal del doble).
Stephanie
44
(este DateTime ignorado) es muy, muy engañoso
Lars Corneliussen
6

Cuando resta 1970 del tiempo actual, tenga en cuenta que el intervalo de tiempo tendrá un campo de milisegundos distinto de cero. Si por alguna razón está interesado en los milisegundos, tenga esto en cuenta.

Esto es lo que hice para solucionar este problema.

 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.
Kelly Anderson
fuente
5

Esto es lo que yo uso.

 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;
        }
}
Matthew James Lewis
fuente
quizás lo convierta en un método de extensión de DateTime
bizzehdee
3

He unido los enfoques más elegantes para este método de utilidad:

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;
}
XDS
fuente
2

Esta solución ayudó en mi situación:

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

usando ayuda en el código:

double ret = DateHelper.DateTimeToUnixTimestamp(DateTime.Now)
Aslan Kystaubayev
fuente
0

Hay un ToUnixTimeMilliseconds para DateTimeOffset en el sistema

Puede escribir un método similar para DateTime:

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

10000000L - convirtiendo ticks a segundos

62135596800L - convirtiendo 01.01.01 a 01.01.1978

No hay problema con Utc y fugas

Timur Lemeshko
fuente
0

A continuación se muestra una clase de extensión de 2 vías que admite:

  • Localización de zona horaria
  • Entrada \ salida en segundos o milisegundos.

En el caso de OP, el uso es:

DateTime.Now.ToUnixtime();

o

DateTime.UtcNow.ToUnixtime();

Aunque existe una respuesta directa, creo que usar un enfoque genérico es mejor. Especialmente porque es muy probable que un proyecto que necesite una conversión como esta, también necesite estas extensiones de todos modos, por lo que es mejor usar la misma herramienta para todos.

    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;
            }
        }
    }
SingleFlake
fuente
Tenga cuidado de no confundir los formatos de milisegundos y segundos (el mejor de los casos es una excepción, el peor es la conversión ilógica). De manera predeterminada, la entrada / salida tiene el formato de milisegundos. Si prefiere usar el formato de segundos como predeterminado, simplemente cambie isInMilliseconds = true (en ambos métodos) a falso.
SingleFlake
0

Usé esto después de luchar por un tiempo, también atiende el desplazamiento de la zona horaria:

    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;
    }
Bruce Cameron
fuente
-1

El código simple que estoy usando:

public static long CurrentTimestamp()
{
   return (long)(DateTime.UtcNow.Subtract(new DateTime(1970, 1, 1)).TotalSeconds * 1000);
}

Este código proporciona una marca de tiempo de Unix, milisegundos totales desde 1970-01-01 hasta ahora.

Erkin Eren
fuente