Obtenha DateTime.Now com precisão de milissegundos

231

Como posso exatamente construir um carimbo de data / hora com precisão de milissegundos?

Preciso de algo como 16.4.2013 9: 48: 00: 123. Isso é possível? Eu tenho um aplicativo, onde colho exemplos de valores 10 vezes por segundo e preciso mostrá-los em um gráfico.

LuckyHK
fonte
Esteja ciente de que várias respostas estão sendo usadas hhpor horas (horário padrão). No caso de um registro de data e hora (e em muitos outros casos), isso provavelmente deve ser associado a tt(am / pm) ou substituído por HH(horário militar).
Wentz

Respostas:

304

Como posso exatamente construir um carimbo de data / hora com precisão de milissegundos?

Eu suspeito que você quer dizer precisão de milissegundos . DateTimetem muita precisão, mas é bastante grosseiro em termos de precisão. De um modo geral, você não pode. Normalmente, o relógio do sistema (que é o local de onde DateTime.Nowos dados são obtidos) tem uma resolução de cerca de 10 a 15 ms. Consulte a publicação no blog de Eric Lippert sobre precisão e exatidão para obter mais detalhes.

Se você precisar de um tempo mais preciso do que isso, convém usar um cliente NTP.

No entanto, não está claro que você realmente precise de uma precisão de milissegundos aqui. Se você não se importa com o tempo exato - você só quer mostrar as amostras na ordem certa, com uma precisão "muito boa", o relógio do sistema deve estar bem. Aconselho você a usar, em DateTime.UtcNowvez de DateTime.Nowevitar, problemas de fuso horário em torno das transições de horário de verão, etc.

Se a sua pergunta é , na verdade, apenas em torno converter uma DateTimea uma corda com uma precisão de milissegundos, eu sugiro usar:

string timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff",
                                            CultureInfo.InvariantCulture);

(Observe que, diferentemente de sua amostra, é possível classificá-lo e é menos provável que cause confusão quanto ao fato de ser "mês / dia / ano" ou "dia / mês / ano".)

Jon Skeet
fonte
5
@antonio: Com mais informações do que "não funciona", não posso oferecer mais ajuda.
Jon Skeet
Sim, posso fornecer mais informações: "{0: aaaamMMdd HH: mm: ss.fff}", DateTime.UtcNow -> 20180502 11: 07: 20.000 Win32.GetSystemTime (ref stime) -> 2018,2,5,11 , 7,20,0 (ymdh mm ss ms) Posso criar uma instância de data e hora com milissegundos: var dt = new DateTime (2018, 5, 2, 19, 34, 55, 200); "{0: aaaamMMdd HH: mm: ss.fff}", dt -> 20180502 19: 34: 55.200. Estrutura compacta de rede, Windows Embedded Compact 7, no ARM Cortex-A8
antonio
@antonio: Parece que a versão do .NET que você está usando no hardware que você está usando simplesmente não fornece precisão de subsegundos - ou você chamou isso em um segundo limite. (Se você continuar batendo DateTime.UtcNowrepetidamente, não é sempre apenas incrementar uma vez por segundo Você não demonstraram que?.)
Jon Skeet
Agora, o valor é truncado: Ticks 636534596580000000 DateTime de Ticks 20180205 20: 34: 18.000. a limitação está no hardware / software, eu acho. Eu uso a classe Stopwatch. Obrigado Jon
antonio
@antonio: Provavelmente vale a pena criar uma nova pergunta com todos os detalhes do dispositivo envolvido neste momento.
21818 Jon Skeet
117

Isso deve funcionar:

DateTime.Now.ToString("hh.mm.ss.ffffff");

Se você não precisa que ele seja exibido e precisa saber a diferença de horário, não converta-a em uma String. Apenas deixe como,DateTime.Now();

E use TimeSpanpara saber a diferença entre intervalos de tempo:

Exemplo

DateTime start;
TimeSpan time;

start = DateTime.Now;

//Do something here

time = DateTime.Now - start;
label1.Text = String.Format("{0}.{1}", time.Seconds, time.Milliseconds.ToString().PadLeft(3, '0'));
Pyromancer
fonte
Eu preciso calcular com ele, então não posso convertê-lo em string.
LuckyHK
25

Eu estava procurando uma solução semelhante, com base no que foi sugerido neste segmento, eu uso o seguinte DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss.fff") , e funciona como charme. Nota: esses .fffsão os números de precisão que você deseja capturar.

Jozcar
fonte
1
Se a data for à tarde (16:00) será exibida como pela manhã. CORRECÇÃO: Use HH(horário militar) ou adicione tt(PM ou AM). Como mostrado neste exemplo: repl.it/KGr3/1
Jaider
22

Use a estrutura DateTime com milissegundos e formato como este:

string timestamp = DateTime.UtcNow.ToString("yyyy-MM-dd HH:mm:ss.fff", 
CultureInfo.InvariantCulture);
timestamp = timestamp.Replace("-", ".");
Jacman
fonte
16

A resposta do Pyromancer me parece muito boa, mas talvez você queira:

DateTime.Now.Millisecond

Mas se você estiver comparando datas, o TimeSpan é o caminho a percorrer.

Renae
fonte
15
Nota: Se você estiver comparando a diferença entre dois DateTimes como um TimeSpan, precisará TotalMilliseconds. Milissegundos contém o contador atual de milissegundos, que nunca é maior que 1000, enquanto TotalMilissegundos mantém o total de milissegundos decorridos desde a época.
Contango 12/09/14
4

Se você ainda deseja uma data em vez de uma sequência como as outras respostas, basta adicionar este método de extensão.

public static DateTime ToMillisecondPrecision(this DateTime d) {
    return new DateTime(d.Year, d.Month, d.Day, d.Hour, d.Minute,
                        d.Second, d.Millisecond, d.Kind);
}
bétula
fonte
3

Tanto quanto eu entendo a pergunta, você pode ir para:

DateTime dateTime = DateTime.Now;
DateTime dateTimeInMilliseconds = dateTime.AddTicks(-1 * dateTime.Ticks % 10000); 

Isso cortará os tiquetaques menores que 1 milissegundo.

Roland Dietz
fonte
Sim, mas a resolução real do DateTime.Now não pode ser superior a 16 ms.
Peter Mortensen
2

O problema DateTime.UtcNowe DateTime.Nowé que, dependendo do computador e do sistema operacional, ele pode ter precisão de apenas 10 a 15 milissegundos. No entanto, nos computadores Windows, pode-se usar a função de baixo nível GetSystemTimePreciseAsFileTime para obter precisão de microssegundos, consulte a função GetTimeStamp()abaixo.

    [System.Security.SuppressUnmanagedCodeSecurity, System.Runtime.InteropServices.DllImport("kernel32.dll")]
    static extern void GetSystemTimePreciseAsFileTime(out FileTime pFileTime);

    [System.Runtime.InteropServices.StructLayout(System.Runtime.InteropServices.LayoutKind.Sequential)]
    public struct FileTime  {
        public const long FILETIME_TO_DATETIMETICKS = 504911232000000000;   // 146097 = days in 400 year Gregorian calendar cycle. 504911232000000000 = 4 * 146097 * 86400 * 1E7
        public uint TimeLow;    // least significant digits
        public uint TimeHigh;   // most sifnificant digits
        public long TimeStamp_FileTimeTicks { get { return TimeHigh * 4294967296 + TimeLow; } }     // ticks since 1-Jan-1601 (1 tick = 100 nanosecs). 4294967296 = 2^32
        public DateTime dateTime { get { return new DateTime(TimeStamp_FileTimeTicks + FILETIME_TO_DATETIMETICKS); } }
    }

    public static DateTime GetTimeStamp() { 
        FileTime ft; GetSystemTimePreciseAsFileTime(out ft);
        return ft.dateTime;
    }
Estocástico
fonte
Muito obrigado. Eu tenho procurado isso por tanto tempo. Isso causa problemas de desempenho e é seguro usar o código de produção?
Muhammet Göktürk Ayan
-2
public long millis() {
  return (long.MaxValue + DateTime.Now.ToBinary()) / 10000;
}

Se você deseja microssegundos, mude 10000para 10e, se quiser o 10º de micro, exclua / 10000.

notável
fonte
-3

DateTime.Now.ToString ("ddMMyyyyhhmmssffff")

amol jadhao
fonte