2016-11-14 19 views
9

Làm cách nào để xác định ngày trong tuần ở California (Giờ Thái Bình Dương) dựa trên dấu thời gian Unix tùy ý (giây)? Tôi đã tìm kiếm xung quanh, nhưng không tìm thấy một thư viện tích hợp cho C++.Chuyển đổi dấu thời gian unix (s) sang ngày trong tuần bằng C++?

UTC thường là 8 giờ trước PT, nhưng chỉ đơn giản là trừ 8 giờ từ dấu thời gian Unix và tạo cấu trúc tm không hoạt động vì các yếu tố tiết kiệm ánh sáng ban ngày giảm giá này.

+1

Tôi không downvote bạn nhưng làm thế nào về ['std :: localtime'] (http://en.cppreference.com/w/cpp/chrono/c/localtime)? – Danh

+1

Cảm ơn bạn - nếu thời gian địa phương không phải là PT cho tôi thì sao? –

+3

[strftime] (http://en.cppreference.com/w/cpp/chrono/c/strftime). Hoặc [time_put] (http://en.cppreference.com/w/cpp/locale/time_put). Hoặc [ngày của Howard Hinnant] (https://github.com/HowardHinnant/date) - con trỏ, không phải là câu trả lời, đây là lý do tại sao một bình luận. –

Trả lời

9

Dưới đây là cách thực hiện bằng cách sử dụng Howard Hinnant's date library. Đây là một miễn phí MIT cấp phép C++ 11/14 thư viện dựa trên <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'; 
} 

Dòng đầu tiên chỉ xây dựng dấu thời gian unix (mà bạn có thể có từ các nguồn khác). Trong C++ 11 chúng tôi không có chrono-literals và do đó dòng này sẽ thay là:

auto unix_timestamp = sys_seconds{seconds{1479664467}}; 

make_zoned() tạo ra một zoned_time<seconds> dựa trên unix_timestamptime_zone "America/Los_Angeles". A zoned_time là bộ sưu tập của time_zone và dấu thời gian unix.

Bạn có thể lấy giờ địa phương ở số zoned_time bằng zt.get_local_time(). Đây là chrono::time_point nhưng không có đồng hồ nào được liên kết với nó. Độ chính xác của thời điểm này sẽ bằng với độ chính xác của dấu thời gian ban đầu của bạn (giây trong trường hợp này).

Bạn có thể lấy ngày địa phương trong tuần của local_time bằng cách cắt xén các local_time đến một độ chính xác của days:

floor<days>(zt.get_local_time()) 

Và đây ngày chính xác time_point sẽ chuyển đổi thành loại weekday.

A weekday có thể được in ra, tham gia weekday số học và so sánh hoặc được chuyển đổi rõ ràng thành unsigned trong khoảng [0, 6].

Chương trình

đầu ra ở trên:

Sun 

Phần múi giờ của thư viện này là một đại diện trung thành của IANA timezone database. Nó sẽ cung cấp các điều chỉnh chính xác giữa các múi giờ địa phương và UTC như xa trở lại vào giữa những năm 1800 đến hết ngày nay. Nếu bạn vượt qua dấu thời gian của thư viện trước khoảng giữa 1800, giá trị UTC sớm nhất được biết đến sẽ được ngoại suy ngược về năm -32768. Bạn cũng có thể vượt qua dấu thời gian trong tương lai như năm 32767 và các quy tắc tiết kiệm ánh sáng ban ngày và bù trừ hiện tại sẽ được truyền đi về phía trước.

Vì thư viện này được xây dựng trên <chrono>, nó sẽ xử lý bất kỳ độ chính xác nào mà nguồn cung cấp <chrono>. Lưu ý rằng một số chrono::duration s chẳng hạn như nanoseconds có phạm vi hạn chế hơn (+/- 292 năm cho nanoseconds).

Thư viện/quy trình là chuỗi an toàn. Tức là, chương trình hoạt động trực tiếp với bất kỳ múi giờ nào bạn chỉ định mà không thay đổi múi giờ hoặc biến môi trường của máy tính của bạn dưới mui xe. Nó cũng không liên quan đến một phần của API định thời C, được biết là không an toàn bởi vì các hàm không thuộc địa phương của hàm const.

Được chuyển đến các phiên bản gcc, clang và VS gần đây.

1

Bạn có thể sử dụng thư viện Boost không? Nếu bạn có thể tìm ra chuỗi múi giờ Posix (IEEE Std 1003.1, xem http://www.boost.org/doc/libs/1_62_0/doc/html/date_time/local_time.html#date_time.local_time.posix_time_zone) cho múi giờ của bạn (PST), thì ví dụ bên dưới có thể hữu ích.

#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; 
} 
2

cách Hacky sử dụng tiêu chuẩn UNIX C (không đề an toàn phiên bản):

#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(); 
} 

Thật không may, TZ env var hoặc thay đổi các tập tin /etc/localtime là những cách duy nhất bạn có thể ảnh hưởng đến các thiết lập múi giờ cho các chức năng thời gian UNIX (Theo mui xe tzset() sử dụng các nguồn này để khởi tạo một tập hợp các biến được chia sẻ mã hóa cài đặt múi giờ cho tất cả các hàm thư viện).

Một vấn đề là bạn cần phải đi kèm với (các) chuỗi UNIX TZ cho (các) khu vực bạn cần. Định dạng zoneinfo là định dạng đơn giản nhất và được đề xuất để sử dụng. Tôi đã sử dụng tzselect để tạo giá trị TZ đó cho giờ Thái Bình Dương.

Đồng thời xem man 5 localtime, man tzselect để biết thông tin về thiết lập múi giờ UNIX chuẩn.

Các vấn đề liên quan