2016-04-08 13 views
9

Thực tế thú vị rằng tôi chắc chắn hầu hết chúng ta có thể chơi trong các cõi thời gian biết - có ngày/giờ có thể xuất hiện hợp lệ nhưng thực sự không tồn tại, ví dụ: 2:30 sáng theo giờ chuyển đổi tiết kiệm ban ngày.Có cách nào để xác định ngày/giờ không tồn tại không?

Có cách nào trong C++ (tiêu chuẩn hoặc Windows) để tìm hiểu xem ngày/giờ đã cho có hợp lệ trong một đặc điểm múi giờ nhất định không?

+0

Một câu hỏi thú vị, chắc chắn. Bạn cũng cần hỗ trợ bước nhảy vọt trong ngày thứ hai, như ngày 30 tháng 6 năm 2015, 23,59,60? (Nếu để các quy tắc ra khỏi API thời gian của Google), tôi nghĩ * tăng thư viện ngày giờ sẽ là điểm khởi đầu tốt nhất.Tôi sử dụng những thư viện này nhưng không sử dụng cho điều đặc biệt này. – Bathsheba

+0

Tôi đã gắn thẻ "boost-date-time" và, có lẽ là vô nghĩa, "tăng" vì tôi tưởng tượng một giải pháp có thể có sẵn trong hộp cho điều này, hoặc không đặc biệt khó thực hiện trong khuôn khổ đó. – Bathsheba

+0

Thư viện C++ tiêu chuẩn không hoạt động với thời gian. Nếu bạn nhắm mục tiêu Windows thì bạn có thể sử dụng SystemTimeToFileTime() hoặc SystemTimeToTzSpecificLocalTime(). Việc gửi một ngày không hợp lệ làm cho hàm bị lỗi với ERROR_INVALID_PARAMETER. Nếu nó phải là nền tảng chéo thì bạn phải đi mua sắm cho một thư viện. –

Trả lời

0

Định dạng time_t là giá trị số nguyên (giây kể từ 1/1/1970 00:00 UTC) vì vậy mọi giá trị có thể có của time_t tồn tại (trong giới hạn của kiểu số nguyên được sử dụng tất nhiên). Mặt khác, không phải tất cả các giá trị có thể có của "struct tm" (nơi bạn có thành viên cho ngày, tháng, năm, giờ, phút và giây) tồn tại (và điều này có thể là ý của bạn). Để kiểm tra xem liệu "struct tm" có tồn tại hay không, bạn phải làm như sau:

  • Đặt thành viên tm_isdst thành -1. Điều này chỉ ra rằng bạn không biết liệu DST của nó hay không.
    • Chuyển đổi "struct tm" thành time_t bằng mktime().
    • Chuyển đổi time_t trở lại thành "struct tm" bằng localtime().
    • So sánh kết quả "struct tm" với "struct tm" ban đầu, bỏ qua trường tm_isdst (hoặc sử dụng nó để xem bạn có đang ở DST hay không).
+0

'mktime' sẽ làm gì nếu bạn cung cấp giá trị lúc 02:30 khi quay lại thời gian bình thường? Vấn đề ở đây là thời gian lịch sẽ lặp lại 02: xx giờ hai lần (một lần với dst và một lần không có). Nếu bạn không biết bạn có nghĩa là máy tính có thể không thể cho bạn biết ... – skyking

+0

Tiêu chuẩn không yêu cầu 'time_t' là một số nguyên, nhưng nếu không có vẻ như tiêu chuẩn sẽ ngụ ý rằng giải pháp của bạn sẽ hoạt động . Nếu nó thực sự sẽ làm việc trên việc thực hiện là một câu hỏi khá ... – skyking

+1

@ Skyking: bạn nói đúng (một phần). Khi đồng hồ được đặt trở lại trong một giờ (DST -> không phải DST), và bạn không xác định xem bạn đang ở trong DST hay không, CRT sẽ đoán, nhưng ít nhất tôi hy vọng rằng nó sẽ trả về 2: 30 DST hoặc 2:30 không phải DST. Dù sao, cách tốt nhất để kiểm tra nó là thử nó. Kết quả thực sự có thể phụ thuộc vào việc thực hiện CRT. – Patrick

1

Sử dụng này 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'; 
    } 
} 

Kết quả của chương trình này là:

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 

Nói tóm lại, chương trình này cố gắng dịch một ngày locale/thời gian 2016- 03-13 02:30:00 đến UTC sử dụng múi giờ "America/New_York". Bản dịch ném một ngoại lệ vì giờ địa phương không tồn tại. Một ngoại lệ cũng được ném (với một thông báo lỗi khác), nếu thời gian cục bộ không rõ ràng, chẳng hạn như khi thiết lập đồng hồ địa phương trở lại từ tiết kiệm ánh sáng ban ngày.

Thư viện cũng cung cấp cú pháp để tránh những ngoại lệ này nếu đó là mong muốn.

Điều này hoạt động trên VS-2013, VS-2015, clang và gcc. Nó đòi hỏi C++ 11, C++ 14 hoặc C++ 1z.

Liên kết ở trên trỏ đến tài liệu. Đây là kho github:

https://github.com/HowardHinnant/date

0

Sử dụng chức năng đặc trưng cho Windows, bạn có thể làm a call toTzSpecificLocalTimeToSystemTime() Tiếp theo a call toSystemTimeToTzSpecificLocalTime() với múi giờ có liên quan.

Sau khi hoàn thành, nếu hai khác nhau bạn có thời gian không hợp lệ khi TzSpecificLocalTimeToSystemTime chuyển đổi thời gian không hợp lệ thành thời gian "thực".

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

    return (st != st2); 
} 
Các vấn đề liên quan