Función que crea una marca de tiempo en c #

101

Me preguntaba, ¿hay alguna manera de crear una marca de tiempo en c # a partir de una fecha y hora? Necesito un valor de precisión de milisegundos que también funcione en Compact Framework (diciendo que, dado que DateTime.ToBinary () no existe en CF).

Mi problema es que quiero almacenar este valor de una manera independiente de la base de datos para poder ordenarlo más tarde y averiguar qué valor es mayor de otro, etc.

Konstantinos
fuente
2
La respuesta aceptada aquí ofrece una buena solución, pero si desea una marca de tiempo real, consulte esta Q / A: stackoverflow.com/questions/9814060/…
inanutshellus

Respuestas:

206

Siempre uso algo como lo siguiente:

public static String GetTimestamp(this DateTime value)
{
    return value.ToString("yyyyMMddHHmmssfff");
}

Esto le dará una cadena como 200905211035131468, ya que la cadena va desde los bits de orden más alto de la marca de tiempo hasta la clasificación de cadena simple de orden más bajo en sus consultas SQL se puede usar para ordenar por fecha si está pegando valores en una base de datos

RobV
fuente
5
¿Por qué tienes 21 meses y solo tienes 12? :)
PaulB
2
El token para el año debe estar en minúsculas aquí: return value.ToString ("yyyyMMddHHmmssffff");
Don Cote
1
@RobV La pregunta solicita una precisión de milisegundos, por lo que necesita 3 'f al final. Sus 4 'f dan una precisión de 100 microsend.
Eugene Beresovsky
2
Tenga en cuenta que Compact Framework no transfiere milisegundos. Siempre serán 0. Tienes que modificar el código y agregar algo como esto: int tick = Environment.TickCount% 1000; int ms = (tick> = MOffset)? (tick - MOffset): (1000 - (MOffset - tick)); ms = Math.Min (999, Math.Max ​​(0, ms));
Redwolf
43

Creo que puede crear una marca de fecha de estilo Unix con una precisión de un segundo utilizando lo siguiente

//Find unix timestamp (seconds since 01/01/1970)
long ticks = DateTime.UtcNow.Ticks - DateTime.Parse("01/01/1970 00:00:00").Ticks;
ticks /= 10000000; //Convert windows ticks to seconds
timestamp = ticks.ToString();

Ajustar el denominador le permite elegir su nivel de precisión

Voxel
fuente
19

Puede usar la propiedad DateTime.Ticks, que es un almacenamiento largo y universal, siempre en aumento y también utilizable en el marco compacto. Solo asegúrese de que su código no se use después del 31 de diciembre de 9999;)

Frans Bouma
fuente
Cuando dices "siempre aumentando", no hay garantía de que dos llamadas a DateTime.UtcNow.Ticks den valores diferentes, ¿verdad? En otras palabras, todavía necesita algo de precaución antes de usarlo como una marca de tiempo única.
Jon Skeet
9
@Konstantinos: no puede evitar los duplicados si usa marcas de tiempo. Las marcas de tiempo no se utilizan para claves únicas, sino para marcar una hora. Dijiste que necesitabas una precisión de milisegundos y los ticks tienen una precisión de 100 ns. Lo que pasa es que tendrás duplicados. Si no lo desea, necesita una secuencia única en la base de datos, que desafortunadamente no es agnóstica de la base de datos.
Frans Bouma
3
"es un recuento real de garrapatas que aumenta con el tiempo". Pero el reloj del sistema puede retroceder, por ejemplo, al final del horario de verano si está usando la hora local, o porque se ajustó el reloj del sistema.
Joe
1
@Frans: absolutamente. Solo hice el comentario porque la gente debería pensar en las implicaciones de la solución que elijan. Por ejemplo, usaría UTC en lugar de la hora local para al menos eliminar los problemas de DST.
Joe
1
@konstantinos: hmm ... los docs dicen que tiene una precisión de 100ns, por lo que es realmente extraño que no tenga la precisión documentada. Quizás sea el marco compacto de hecho, no es un marco sin errores
Frans Bouma
6

También puedes usar

Stopwatch.GetTimestamp (). ToString ();

mgokhanbakal
fuente
4

cuando lo necesite en una marca de tiempo en segundos, puede usar lo siguiente:

var timestamp = (int)(DateTime.Now.ToUniversalTime() - new DateTime(1970, 1, 1)).TotalSeconds;
Adi_Pithwa
fuente
2

Si desea marcas de tiempo que correspondan a tiempos reales reales, PERO también desea que sean únicas (para una instancia de aplicación determinada), puede usar el siguiente código:

public class HiResDateTime
{
   private static long lastTimeStamp = DateTime.UtcNow.Ticks;
   public static long UtcNowTicks
   {
       get
       {
           long orig, newval;
           do
           {
               orig = lastTimeStamp;
               long now = DateTime.UtcNow.Ticks;
               newval = Math.Max(now, orig + 1);
           } while (Interlocked.CompareExchange
                        (ref lastTimeStamp, newval, orig) != orig);

           return newval;
       }
   }
}
Ian Mercer
fuente