преобразование даты и времени — конвертировать метки времени Unix в день недели в C ++?

Как я могу определить день недели в Калифорнии (по тихоокеанскому времени) по произвольной метке времени Unix (секунды)? Я искал вокруг, но не нашел встроенную библиотеку для C ++.

UTC, как правило, на 8 часов опережает PT, но просто вычитает 8 часов из метки времени Unix и создает tm struct не работает, так как при этом учитываются нюансы летнего времени.

9

Решение

Вот как это сделать, используя Библиотека дат Говарда Хиннанта. Это бесплатная 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.

9

Другие решения

Хакерский способ с использованием стандартного 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.

2

Вы можете использовать библиотеку 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;
}
1
По вопросам рекламы [email protected]