2016-04-08 2 views
9

Удовлетворительный факт, что я уверен, что большинство из нас, кто может играть во время царства, знают - есть дата/время, которое может показаться действительным, но на самом деле его не существует, например. 2:30 утра при переключении на летнее время.Есть ли способ определить, нет ли даты/времени?

Есть ли способ в C++ (стандарт или Windows) выяснить, действительно ли данная дата/время действительна в данной спецификации часового пояса?

+0

Интригующий вопрос, обязательно. Вам также нужно поддерживать прыжок на второй день, например 30 июня 2015 года, 23.59.60? (Если это исключает API времени Google), я думаю, что * ускорить использование библиотек времени и времени будет лучшей отправной точкой.Я использую эти библиотеки, но не для этой конкретной вещи. – Bathsheba

+0

Я отметил «форсировать дату-время» и, возможно, «новизну», поскольку я предполагаю, что решение может быть доступно из коробки для этого или не особенно сложно реализовать в этой структуре. – Bathsheba

+0

Стандартная библиотека C++ не справляется со временем. Если вы нацеливаете Windows, вы можете использовать SystemTimeToFileTime() или SystemTimeToTzSpecificLocalTime(). Передача плохой даты приводит к сбою функции с ERROR_INVALID_PARAMETER. Если он должен быть кросс-платформенным, вам нужно пойти за покупками в библиотеку. –

ответ

0

Формат time_t представляет собой целочисленное значение (секунды с 01.01.1970 00:00 по UTC), поэтому существует все возможные значения time_t (в пределах используемого конечно-целого типа).

С другой стороны, существуют не все возможные значения «struct tm» (где у вас есть члены для дня, месяца, года, часа, минуты и секунды) (и это, вероятно, то, что вы имеете в виду). Чтобы проверить, существует ли «struct tm», вам необходимо сделать следующее:

  • Установить элемент tm_isdst на -1. Это означает, что вы не знаете, является ли его DST или нет.
    • Преобразование «struct tm» в time_t с использованием mktime().
    • Преобразуйте time_t обратно в "struct tm", используя localtime().
    • Сравните полученную "struct tm" с исходной "struct tm", проигнорируйте поле tm_isdst (или используйте его, чтобы увидеть, находитесь ли вы в DST или нет).
+0

Что делает 'mktime', если вы отправляете значение в 02:30, когда возвращаетесь к обычному времени? Проблема здесь в том, что календарное время будет повторяться 02: xx час дважды (один раз с dst и один раз без). Если вы не знаете, что вы имеете в виду, то, возможно, компьютер не может сказать вам ... – skyking

+0

Стандарт не требует, чтобы 'time_t' был целым числом, но в противном случае кажется, что стандарт будет означать, что ваше решение будет работать , Если он действительно будет работать над реализацией, это еще один вопрос ... – skyking

+1

@Skyking: вы правы (частично). Когда часы устанавливаются на один час (DST -> не-DST), и вы не указываете, находитесь ли вы в летнем времени или нет, CRT догадается, но, по крайней мере, я надеюсь, что он вернет либо 2: 30 DST или 2:30 не-DST. В любом случае, лучший способ проверить это - попробовать. Результат может действительно зависеть от реализации ЭЛТ. – Patrick

1

Используя этот free, open-source library:

#include "tz.h" 
#include <iostream> 

int 
main() 
{ 
    using namespace date; 
    using namespace std::chrono_literals; 
    try 
    { 
     auto zone = locate_zone("America/New_York"); 
     zone->to_sys(local_days{mar/13/2016} + 2h + 30min); 
    } 
    catch (const std::exception& e) 
    { 
     std::cout << e.what() << '\n'; 
    } 
} 

Вывод этой программы:

2016-03-13 02:30 is in a gap between 
2016-03-13 02:00:00 EST and 
2016-03-13 03:00:00 EDT which are both equivalent to 
2016-03-13 07:00:00 UTC 

Короче говоря, эта программа пытается перевести дату локаль/время 2016- 03-13 02:30:00 по UTC, используя часовой пояс «Америка/Нью-Йорк». Перевод выдает исключение, потому что локального времени не существует. Также генерируется исключение (с другим сообщением об ошибке), если местное время неоднозначно, например, при настройке локальных часов назад с летнего времени.

Библиотека также предоставляет синтаксис для исключения этих исключений, если это желание.

Это работает на VS-2013, VS-2015, clang и gcc. Для этого требуется C++ 11, C++ 14 или C++ 1z.

Ссылка выше указывает на документацию. Вот хранилище GitHub:

https://github.com/HowardHinnant/date

0

Использование функций Windows, специфичные, вы можете сделать a call toTzSpecificLocalTimeToSystemTime() с последующим a call toSystemTimeToTzSpecificLocalTime() с соответствующей временной зоне.

По завершении, если они отличаются друг от друга, у вас есть недействительное время, так как TzSpecificLocalTimeToSystemTime преобразует недействительное время в «реальное» время.

bool IsValidTime(TIME_ZONE_INFORMATION tz, SYSTEMTIME st) 
{ 
    SYSTEMTIME utcSystemTime, st2; 
    TzSpecificLocalTimeToSystemTime(&tz, &st, &utcSystemTime); 
    SystemTimeToTzSpecificLocalTime(&tz, &utcSystemTime, &st2); 

    return (st != st2); 
} 
Смежные вопросы