Мне нужно преобразовать временную метку в формате RFC-3339 (например, «2024-01-04T14:30:00.119919872Z») в наносекундную временную метку Unix (например, 1704378600119919872). Однако максимальная точность структур DateTime в C# составляет всего 100 наносекунд. Например:
string timestamp = "2024-01-04T14:30:00.119919872Z";
DateTime dt = DateTime.Parse(timestamp);
Console.WriteLine(dt.ToString("O")); // outputs: 2024-01-04T09:30:00.1199199-05:00
Таким образом, доли секунды в метке времени округляются до 1199199 — ближайших 100 наносекунд. Судя по всему, 100 наносекунд — это точность структур DateTime.
Чтобы избежать потери точности, я написал свой собственный метод синтаксического анализа, но он очень уродлив:
public static long ToUnixNanoseconds(string str)
{
string dateTimeStr = str[..19];
DateTime utcDateTime = DateTime.Parse(dateTimeStr + "Z");
long unixTimeSeconds = (new DateTimeOffset(utcDateTime)).ToUnixTimeSeconds();
string fractionalSecondsStr = str[19..(str.Length - 1)];
decimal fractionalSeconds = decimal.Parse(fractionalSecondsStr);
long unixNano = (long)((unixTimeSeconds + fractionalSeconds) * 1000000000);
return unixNano;
}
Какие существуют лучшие способы преобразования временной метки RFC-3339 в временную метку Unix с точностью до наносекунды в C#?
Итак, нет ли поддержки времени анализа с полной наносекундной точностью? :(
Проверьте github.com/nodatime/nodatime
Я думаю, что это реализация, хотя сомневаюсь, что вы захотите использовать ее повторно. github.com/dotnet/runtime/blob/…
зачем вам нужна точность меньше 100 наносекунд. ?
@MitchWheat В моем случае я анализирую объекты данных финансового рынка с наносекундными временными метками Unix. Округление на два порядка точности будет означать, что порядок, в котором происходят события, не сохраняется. В мире финансов все происходит очень быстро.
@Treker: Я бы сказал, что если вы полагаетесь на порядок с точностью менее 100 наносекунд, то ваш дизайн может быть сломан. Например: эти события происходят из нескольких систем? У них у всех есть атомные часы?
Событиями являются сделки и котировки, которые происходят на различных фондовых биржах и обрабатываются и консолидируются организациями, называемыми SIP (обработчиками информации о ценных бумагах). В США в основном существует два SIP — CTA для акций, котирующихся на NYSE, и UTP для акций, котирующихся на NASDAQ.
Ваш метод синтаксического анализа кажется приемлемым, если вы всегда ожидаете одного и того же формата ввода и не хотите включать полную библиотеку только для этого одного варианта использования (хотя Noda Time действительно хорош.)
Можно было бы немного подправить. Вот мой подход:
public static long ToUnixNanoseconds(ReadOnlySpan<char> timestamp)
{
var seconds = DateTimeOffset.Parse(timestamp[0..19], CultureInfo.InvariantCulture, DateTimeStyles.AssumeUniversal).ToUnixTimeSeconds();
var fractionalSeconds = decimal.Parse(timestamp[19..^1], NumberStyles.AllowDecimalPoint, CultureInfo.InvariantCulture);
return (long)((seconds + fractionalSeconds) * 1000000000);
}
Это верно. Значения C#
DateTime
иDateTimeOffset
измеряются вticks
с «12:00 полуночи, 1 января 0001 года нашей эры (CE)», где интервал составляет 100 наносекунд. (Learn.microsoft.com/en-us/dotnet/fundamentals/runtime-libraries/…)