2012-03-05 25 views
6

Tôi đọc trong hai chuỗi với một Năm, Ngày Julian (ngày năm), giờ, phút và một quan sát.Tại sao mktime() thay đổi ngày của cấu trúc tm của tôi?

tôi kéo các biến có liên quan bằng cách sử dụng sscanf:

sscanf(tide_str1.c_str(), "%d %d %d %d %Lf", &y1, &j1, &h1, &m1, &obs1); 
sscanf(tide_str2.c_str(), "%d %d %d %d %Lf", &y2, &j2, &h2, &m2, &obs2); 

Đối với bộ dữ liệu đặc biệt này, các giá trị là 2011 083 23 22 1,1

sau đó tôi có thể tạo và cư một cấu trúc tm, và chạy mktime , với các cuộc gọi cout vào ngày ở giữa và thay đổi từ 083 đến 364.

int y1=2011, j1=83, h1=23, m1=22; 
struct tm time_struct = {0, 0, 0, 0, 0, 0, 0, 0, 0}, *time_ptr = &time_struct; 
time_t tv_min; 
time_struct.tm_year = y1 - 1900; 
time_struct.tm_yday = j1; 
cout << time_struct.tm_yday << endl; 
time_struct.tm_hour = h1; 
time_struct.tm_min = m1; 
time_struct.tm_isdst = -1; 
cout << time_struct.tm_yday << endl; 
tv_min = mktime(time_ptr); 
cout << time_struct.tm_yday << endl; 

Tại sao lại như vậy? Có phải vì tm_mday và tm_mon được đặt thành 0 không? Ban đầu tôi đã cố gắng không khởi tạo tất cả bằng không, nhưng sau đó mktime trả về -1. Tôi nên làm gì khác nếu tôi chỉ biết ngày trong năm chứ không phải ngày tháng và tháng?

+0

Các ngày trong năm là đôi khi * sai * được gọi là một "Julian Day". Trên thực tế, số [Julian Day] (http://en.wikipedia.org/wiki/Julian_day) là số ngày kể từ ngày 1 tháng 1 năm 4713 trước Công nguyên; nó được sử dụng trong thiên văn học. –

+0

Có, nhưng nó được sử dụng rộng rãi (không chính xác) trong một số ngành nghề nhất định, trong thực tế, là chính xác. Vì vậy, miễn là tất cả mọi người trong một lĩnh vực sử dụng cùng một thuật ngữ ... thông tin liên lạc xảy ra. – RuQu

Trả lời

13

mktime() đang thực hiện những việc cần làm.

Trích dẫn tiêu chuẩn C:

Các mktime chức năng chuyển đổi thời gian bị phá vỡ xuống, thể hiện dưới dạng giờ địa phương, trong cấu trúc được trỏ đến bởi timeptr thành một giá trị thời gian lịch với mã hóa giống với giá trị được trả về bởi chức năng thời gian. Giá trị ban đầu của các thành phần tm_wdaytm_yday thành phần của cấu trúc bị bỏ qua và giá trị ban đầu của các thành phần khác không bị giới hạn trong phạm vi được chỉ ra ở trên. Sau khi hoàn thành thành công, giá trị của các tm_wdaytm_yday thành phần của cấu trúc được đặt phù hợp, và các thành phần khác được thiết lập để đại diện cho thời gian lịch cụ thể, nhưng với giá trị của họ buộc phải phạm vi nêu trên; giá trị cuối cùng của tm_mdayis không được đặt cho đến tm_montm_year được xác định.

mktime() thể tính toán các giá trị của tm_mdaytm_yday từ các thành viên khác; nó không được thiết kế để tính giá trị của các thành viên khác từ các trường đó.

Mặc dù vậy, bạn có thể khởi tạo struct tm với các giá trị nằm ngoài phạm vi. Ví dụ: nếu bạn muốn tm_yday là 200 (ngày thứ 200 của năm), bạn có thể khởi tạo struct tm đại diện cho ngày thứ 200 của tháng 1. mktime() sau đó sẽ chuẩn hóa nó thành ngày chính xác, với giá trị time_t mà sau đó bạn có thể cấp cho gmtime() hoặc localtime().

Dưới đây là một ví dụ đơn giản:

#include <iostream> 
#include <ctime> 

int main() 
{ 
    struct tm t = { 0 }; 
    t.tm_sec = t.tm_min = t.tm_hour = 0; // midnight 
    t.tm_mon = 0;      // January 
    t.tm_year = 2012 - 1900; 
    t.tm_isdst = -1;      // unknown 

    t.tm_mday = 200;      // January 200th? 

    time_t when = mktime(&t); 
    const struct tm *norm = localtime(&when); // Normalized time 

    std::cout << "month=" << norm->tm_mon << ", day=" << norm->tm_mday << "\n"; 
    std::cout << "The 200th day of 2012 starts " << asctime(norm); 
} 

Đầu ra là:

month=6, day=18 
The 200th day of 2012 starts Wed Jul 18 00:00:00 2012 
+0

Tôi đã thử lời khuyên của bạn và khởi tạo như thế này: struct tm time_struct = {0, 0, 0, 200, 200, 0, 200, 0, 0} và kết quả khi tôi gọi lại là ngày 77 khi nó là 83, mà là gần hơn so với 364 từ trước nhưng vẫn tắt. – RuQu

+1

Tiêu chuẩn không đảm bảo thứ tự của các thành viên 'struct tm', do đó, khởi tạo nó như thế sẽ không nhất thiết phải hoạt động. Bạn nên khởi tạo hoặc gán tất cả các thành viên theo tên. Nhưng nếu chúng được khai báo theo thứ tự thông thường, bạn đang khởi tạo 'tm_mday' và' tm_mon' thành 200. Tôi không nghĩ bạn muốn ngày thứ 200, hay đúng hơn là năm 201. (Và đừng quên rằng 'struct tm' số từ 0 đến 11, không phải từ 1 đến 12.) –

+0

Để rõ ràng, nếu tôi muốn năm thứ 83, tôi nên đặt tháng thành 0 và ngày tháng 83? – RuQu

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