Uzyskaj DateTime.Now z dokładnością do milisekund


231

Jak dokładnie skonstruować znacznik czasu rzeczywistego z dokładnością do milisekund?

Potrzebuję czegoś takiego jak 16.4.2013 9: 48: 00: 123. czy to możliwe? Mam aplikację, w której próbkuję wartości 10 razy na sekundę i muszę pokazać je na wykresie.



Pamiętaj, że wiele odpowiedzi używa hhgodzin (czas standardowy). W przypadku znacznika czasu (i w wielu innych przypadkach) należy go prawdopodobnie powiązać z tt(am / pm) lub zastąpić przez HH(czas wojskowy).
poszedł

Odpowiedzi:


304

Jak dokładnie skonstruować znacznik czasu rzeczywistego z dokładnością do milisekund?

Podejrzewam, że masz na myśli milisekundową dokładność . DateTimema dużą precyzję, ale jest dość gruboziarnisty pod względem dokładności. Ogólnie rzecz biorąc, nie możesz. Zwykle zegar systemowy (z którego DateTime.Nowpobiera dane) ma rozdzielczość około 10-15 ms. Więcej informacji można znaleźć w blogu Erica Lipperta na temat precyzji i dokładności .

Jeśli potrzebujesz dokładniejszego pomiaru czasu, możesz rozważyć użycie klienta NTP.

Nie jest jednak jasne, czy naprawdę potrzebujesz tutaj milisekundowej dokładności. Jeśli nie zależy ci na dokładnym czasie - chcesz tylko pokazać próbki we właściwej kolejności, z „całkiem dobrą” dokładnością, to zegar systemowy powinien być w porządku. Radzę DateTime.UtcNowraczej użyć zamiast DateTime.Nowtego, aby uniknąć problemów ze strefą czasową wokół przejść w czasie letnim itp.

Jeśli pytanie jest rzeczywiście tuż konwertowania DateTimena sznurku z dokładnością do milisekund, sugeruję, używając:

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

(Należy pamiętać, że w przeciwieństwie do próbki, jest to możliwe do sortowania i mniej prawdopodobne jest, że spowoduje zamieszanie wokół tego, czy ma to być „miesiąc / dzień / rok” czy „dzień / miesiąc / rok”).


5
@antonio: Nie mając więcej informacji niż „nie działa”, nie mogę udzielić dalszej pomocy.
Jon Skeet

Tak, mogę podać więcej informacji: „{0: rrrrMMdd GG: 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) Mogę utworzyć instancję daty i godziny z milisekundami: var dt = new DateTime (2018, 5, 2, 19, 34, 55, 200); „{0: rrrrMMdd GG: mm: ss.fff}”, dt -> 20180502 19: 34: 55.200 .Net Compact Framework, Windows Embedded Compact 7, na ARM Cortex-A8
antonio

@antonio: Wygląda więc na to, że wersja .NET, której używasz na używanym sprzęcie, po prostu nie zapewnia dokładności poniżej drugiej - lub zdarzyło ci się nazywać ją na drugiej granicy. (Jeśli wciąż uderzasz DateTime.UtcNowwielokrotnie, czy to zawsze zwiększa się tylko raz na sekundę? Nie pokazałeś tego.)
Jon Skeet, 5'18

Kiedy pobieram Ticks z DateTime.Now, wartość jest obcięta: Ticks 636534596580000000 DateTime z Ticks 20180205 20: 34: 18.000. myślę, że ograniczenie dotyczy sprzętu / oprogramowania. Korzystam z klasy Stopwatch, zamiast tego Dzięki Jon
Antonio

@antonio: Prawdopodobnie warto utworzyć nowe pytanie z pełnymi szczegółami na temat urządzenia zaangażowanego w tym momencie.
Jon Skeet

117

To powinno działać:

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

Jeśli nie potrzebujesz go wyświetlać i potrzebujesz tylko znać różnicę czasu, nie przekształcaj go w ciąg znaków. Po prostu zostaw to jakoDateTime.Now();

I użyj, TimeSpanaby poznać różnicę między przedziałami czasowymi:

Przykład

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

Potrzebuję go obliczyć, więc nie mogę przekonwertować go na ciąg.
LuckyHK 16.04.13

25

Szukałem podobnego rozwiązania, na podstawie tego, co zostało zasugerowane w tym wątku, używam następujących DateTime.Now.ToString("MM/dd/yyyy hh:mm:ss.fff") i działa jak urok. Uwaga: .fffsą to liczby precyzyjne, które chcesz uchwycić.


1
Jeśli data jest po południu (16:00) pokaże się jak rano. POPRAWKA: Użyj HH(czas wojskowy) lub dodaj tt(PM lub AM). Jak pokazano w tym przykładzie: repl.it/KGr3/1
Jaider

22

Użyj struktury DateTime z milisekundami i sformatuj ją w następujący sposób:

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

16

Odpowiedź Pyromancer wydaje mi się całkiem dobra, ale może chciałeś:

DateTime.Now.Millisecond

Ale jeśli porównujesz daty, możesz wybrać TimeSpan.


15
Uwaga: jeśli porównujesz różnicę między dwoma DateTimes jako TimeSpan, potrzebujesz TotalMilliseconds. Milliseconds przechowuje bieżący licznik Milliseconds, który nigdy nie jest większy niż 1000, podczas gdy TotalMilliseconds przechowuje całkowite milisekundy, które upłynęły od epoki.
Contango,

4

Jeśli nadal chcesz datę zamiast ciągu, podobnie jak inne odpowiedzi, po prostu dodaj tę metodę rozszerzenia.

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

3

O ile rozumiem pytanie, możesz wybrać:

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

To odetnie kleszcze mniejsze niż 1 milisekunda.


Tak, ale rzeczywista rozdzielczość DateTime.Now nie może być większa niż około 16 ms.
Peter Mortensen

2

Kłopot ze DateTime.UtcNowi DateTime.Nowto, że w zależności od komputera i systemu operacyjnego, może być tylko z dokładnością od 10 do 15 milisekund. Jednak na komputerach z systemem Windows można użyć funkcji niskiego poziomu GetSystemTimePreciseAsFileTime, aby uzyskać dokładność mikrosekundową, patrz funkcja GetTimeStamp()poniżej.

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

Dziękuję bardzo. Tak długo tego szukałem. Czy powoduje to problemy z wydajnością i czy korzystanie z kodu produkcyjnego jest bezpieczne?
Muhammet Göktürk Ayan


-2
public long millis() {
  return (long.MaxValue + DateTime.Now.ToBinary()) / 10000;
}

Jeśli chcesz mikrosekund, po prostu zmień 10000na 10, a jeśli chcesz dziesiątą mikro, usuń / 10000.


Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.