Как я могу определить день недели в Калифорнии (по тихоокеанскому времени) по произвольной метке времени Unix (секунды)? Я искал вокруг, но не нашел встроенную библиотеку для C ++.
UTC, как правило, на 8 часов опережает PT, но просто вычитает 8 часов из метки времени Unix и создает tm
struct не работает, так как при этом учитываются нюансы летнего времени.
Вот как это сделать, используя Библиотека дат Говарда Хиннанта. Это бесплатная M ++-лицензированная библиотека C ++ 11/14, основанная на <chrono>
:
#include "tz.h"#include <iostream>
int
main()
{
using namespace std::chrono_literals;
using namespace date;
auto unix_timestamp = sys_seconds{1479664467s};
auto zt = make_zoned("America/Los_Angeles", unix_timestamp);
auto wd = weekday{floor<days>(zt.get_local_time())};
std::cout << wd << '\n';
}
Первая строка просто создает метку времени Unix (которую вы можете иметь из других источников). В C ++ 11 у нас нет хронологических литералов, и поэтому эта строка будет:
auto unix_timestamp = sys_seconds{seconds{1479664467}};
make_zoned()
создает zoned_time<seconds>
на основе unix_timestamp
и time_zone
«Америка / Los_Angeles». zoned_time
это коллекция time_zone
и метка времени Unix.
Вы можете получить местное время из zoned_time
с zt.get_local_time()
, Это chrono::time_point
но без часов, связанных с этим. Точность этого момента времени будет равна точности вашей первоначальной отметки времени (в данном случае, секунд).
Вы можете получить местный день недели local_time
обрезая local_time
с точностью до days
:
floor<days>(zt.get_local_time())
И этот день точности time_point
преобразует в тип weekday
,
weekday
можно распечатать, участвовать в weekday
арифметика и сравнения, или быть явно преобразованы в unsigned
в диапазоне [0, 6].
Программа выше выводит:
Sun
Часовой пояс этой библиотеки является точным представлением База данных часовых поясов IANA. Это даст правильные настройки между местными часовыми поясами и UTC еще с середины 1800-х годов до сегодняшнего дня. Если вы передадите метки времени библиотеки до середины 1800-х годов, то самое раннее известное смещение UTC будет экстраполировано обратно к году -32768. В будущем вы также можете передать временные метки до 32767 года, и текущее смещение и правила перехода на летнее время будут распространяться вперед.
Как эта библиотека построена на <chrono>
, он будет обрабатывать любую точность, которая <chrono>
принадлежности. Обратите внимание, что некоторые chrono::duration
такие как nanoseconds
имеют более ограниченный диапазон (+/- 292 года для nanoseconds
).
Библиотека / процесс является потокобезопасным. Таким образом, программа работает напрямую с любым часовым поясом, который вы укажете, не меняя часовой пояс компьютера или переменные среды. Он также не включает ту часть API синхронизации C, которая, как известно, не является поточно-ориентированной из-за локальной статики неконстантных функций.
Портировано на последние версии gcc, clang и VS.
Хакерский способ с использованием стандартного UNIX C (не поточно-ориентированная версия):
#include <stddef.h>
#include <stdlib.h>
#include <stdio.h>
#include <time.h>
void print_times() {
char my_buf[100];
time_t now = time(NULL);
printf(ctime(&now));
strftime(my_buf, 100, "DoW=%w Tz=%Z\n", localtime(&now));
printf(my_buf);
}
int main( int argc, char * argv[] ) {
print_times();
setenv("TZ", "America/Los_Angeles", 1);
print_times();
unsetenv("TZ");
print_times();
}
К несчастью, TZ
env var или изменение файла /etc/localtime
это единственный способ повлиять на настройки часового пояса для функций времени UNIX (под капотом tzset () использует эти источники для инициализации набора общих переменных, которые кодируют настройки часового пояса для всех функций библиотеки).
Проблема в том, что вам нужно прийти с UNIX TZ Строка (ы) для зоны (ей) вам нужно. ZoneInfo Формат — это самый простой и рекомендуемый формат для использования. я использовал tzselect
генерировать это значение TZ для тихоокеанского времени.
Также см man 5 localtime
, man tzselect
для получения информации о стандартной настройке часового пояса UNIX.
Вы можете использовать библиотеку Boost?
Если вы можете выяснить строку часового пояса Posix (IEEE Std 1003.1, см. http://www.boost.org/doc/libs/1_62_0/doc/html/date_time/local_time.html#date_time.local_time.posix_time_zone) для вашего часового пояса (PST), тогда приведенный ниже пример может помочь.
#include <iostream>
#include <ctime>
#include <boost/date_time.hpp>
int main(int argc, char ** argv)
{
std::string posix_time_zone_string = "EST-05:00:00"; // you need to change this to the posix time representation of your desired timezone
time_t unix_time = 1479641855; //1479641855 = Sun, 20 Nov 2016 11:37:35 GMT
boost::posix_time::ptime pt = boost::posix_time::from_time_t(unix_time);
std::cout << "time in UTC: " << boost::posix_time::to_iso_extended_string(pt) << std::endl;boost::local_time::time_zone_ptr zone(new boost::local_time::posix_time_zone(posix_time_zone_string));
boost::local_time::local_date_time dt_with_zone(pt, zone);
std::cout << "time in local timezone: " << boost::posix_time::to_iso_extended_string(dt_with_zone.local_time()) << std::endl;
// Get the week day (alternative 1)
std::cout << "local week day integer: " << boost::local_time::to_tm(dt_with_zone).tm_wday << std::endl; // 0=sunday, 1=monday, etc.
// Get the week day (alternative 2)
std::cout << "local week day name: " << dt_with_zone.local_time().date().day_of_week() << std::endl;
std::cout << "local week day integer: " << int(dt_with_zone.local_time().date().day_of_week()) << std::endl;
return 0;
}