Как я могу преобразовать DateTime в количество секунд с 1970 года?

120

Я пытаюсь преобразовать переменную DateTime C # во время Unix, то есть количество секунд с 1 января 1970 года. Похоже, DateTime фактически реализован как количество «тиков» с 1 января 0001 года.

Моя текущая мысль - вычесть 1 января 1970 года из моего DateTime следующим образом:

TimeSpan span= DateTime.Now.Subtract(new DateTime(1970,1,1,0,0,0));
return span.TotalSeconds;

Есть ли способ лучше?

Slider345
источник
1
Возможный дубликат Как преобразовать время эпох в C #?
jpaugh

Ответы:

196

Вот в основном это. Вот методы, которые я использую для преобразования времени эпохи Unix и обратно:

public static DateTime ConvertFromUnixTimestamp(double timestamp)
{
    DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
    return origin.AddSeconds(timestamp);
}

public static double ConvertToUnixTimestamp(DateTime date)
{
    DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc);
    TimeSpan diff = date.ToUniversalTime() - origin;
    return Math.Floor(diff.TotalSeconds);
}

Обновление: Начиная с .Net Core 2.1 и .Net Standard 2.1 DateTime, равный Unix Epoch, может быть получен из статического DateTime.UnixEpoch.

Дэйв Сверски
источник
1
Следует отметить, что если вы хотите преобразовать в миллисекунды для более точных меток времени или совместимости с объектами Javascript Date (), вам необходимо использовать long вместо int для типа метки времени.
Soviut
3
У меня не получилось. Этот ответ
сработал
@Jonny - ToUniversalTime () преобразуется в UTC, поэтому учитывает UTC.
Дэйв Сверски,
4
Источник DateTime = новый DateTime (1970, 1, 1, 0, 0, 0, 0, DateTimeKind.Utc); Интересно, что этого никто не предлагал. Очень часто миллисекунды представляют время UTC. И если у вас t specify this explicitly and somewhere later in code youнет ToUniversalTime (), тогда у вас будет неправильное время Utc, потому что по умолчанию DateTime НЕ Utc.
Steavy
52

Если остальная часть вашей системы в порядке с DateTimeOffset вместо DateTime, есть действительно удобная функция:

long unixSeconds = DateTimeOffset.Now.ToUnixTimeSeconds();
codeMonkey
источник
7
Это более чистый способ, но он доступен только в структуре 4.6 msdn.microsoft.com/en-us/library/…
Оскар Фракседас
1
Ницца. И, конечно же, для перехода от unix к DateTimeOffset вы можете использовать var time = DateTimeOffset.FromUnixTimeSeconds(5000); MS Doc
Джордан,
22

Единственное, что я вижу, это то, что это должно быть с полуночи 1 января 1970 года по всемирному координированному времени.

TimeSpan span= DateTime.Now.Subtract(new DateTime(1970,1,1,0,0,0, DateTimeKind.Utc));
return span.TotalSeconds;
CaffGeek
источник
7
Это должно быть DateTime.UtcNow?
oferei
14

Вероятно, вы захотите использовать DateTime.UtcNow, чтобы избежать проблемы с часовым поясом

TimeSpan span= DateTime.UtcNow.Subtract(new DateTime(1970,1,1,0,0,0)); 
Дэвид
источник
Единственный способ избежать проблем с часовыми поясами - это 1) оставаться в блаженном неведении и поддерживать только один часовой пояс или 2) обрабатывать часовые пояса (по крайней мере) везде, где вы взаимодействуете с другой системой или конечным пользователем. В частности, использование UTC повсюду внутри компании - это только часть битвы. В первом сценарии добавление времени UTC усугубляет проблему, пока вы не будете готовы выполнить все (2), потому что вы переходите от поддержки любого часового пояса к поддержке только UTC.
jpaugh
1

Такой подход будет хорош, если дата-время, о которой идет речь, находится в формате UTC или представляет местное время в области, в которой никогда не наблюдалось летнее время. Подпрограммы разницы DateTime не принимают во внимание переход на летнее время и, следовательно, будут рассматривать полночь 1 июня как кратную 24 часам после полуночи 1 января. Я не знаю ничего в Windows, что сообщает исторические правила перехода на летнее время для текущего locale, поэтому я не думаю, что есть хороший способ правильно обрабатывать любое время до последнего изменения правила перехода на летнее время.

Supercat
источник
0

Вы можете создать startTime и endTime для DateTime, а затем выполнить endTime.Subtract (startTime). Затем выведите свой промежуток в секундах.

Я думаю, это должно сработать.

Алек Сэнгер
источник
0

Я использую в своих расчетах 2000 год вместо Эпохи. Работу с меньшими числами легко хранить и транспортировать, а также поддерживает JSON.

2000 год оказался вторым 946684800 отсчетов времени.

2000 год был вторым 63082281600 с 1 января 0001 года.

DateTime.UtcNow Тики начинаются с 1 января 0001 года

Секунды с 2000 года :

DateTime.UtcNow.Ticks/10000000-63082281600

Секунды от времени Unix:

DateTime.UtcNow.Ticks/10000000-946684800

Например, 2020 год:

var year2020 = (new DateTime ()). AddYears (2019) .Ticks; // Потому что DateTime начинается уже в год 1

637134336000000000 тиков с 01.01 0001 г.

63713433600 Секунды с 1 января 0001 г.

1577836800 секунд с Великой эпохи

631152000 секунд с 2000 года

Ссылки:

Конвертер времени эпохи: https://www.epochconverter.com

Конвертер первого года: https://www.epochconverter.com/seconds-days-since-y0

profimedica
источник