2013-01-02 42 views
7
#include <stdio.h> 
#include <time.h> 

int main(int argc, char* argv[]) 
{ 
    struct tm stm; 
    stm.tm_sec = 27; 
    stm.tm_min = 5; 
    stm.tm_hour = 18; 
    stm.tm_mday = 2; 
    stm.tm_mon = 0; 
    stm.tm_year = 43; 
    stm.tm_wday = 0; 
    stm.tm_yday = 0; 
    printf("%d\n", mktime(&stm)); 
    getchar(); 
    return 0; 
} 

in -1mktime -1 khi đưa ra một struct tm hợp lệ

Tôi đang hiểu lầm gì?

[+ chỉnh sửa] mục này đang sử dụng Visual Studio 2012 với mục tiêu 32 bit. Tôi đoán một câu hỏi tiếp theo sẽ là 'phương pháp được đề xuất để lưu trữ các giá trị ngày/thời gian tùy ý (nghĩa là những giá trị nào có thể trước 1900)?'

+1

Tại sao bạn không kiểm tra 'errno' hoặc sử dụng' perror' để tìm hiểu xem có gì sai? –

+0

ai đó đã xóa câu trả lời, đó là năm không hợp lệ - Tôi đang sử dụng phiên bản strptime có năm từ năm 1970 thay vì 1900. –

+0

Tôi đã xóa câu trả lời tạm thời, tôi cần kiểm tra điều gì đó (tôi đã đúng lần đầu tiên) – benjarobin

Trả lời

13

Trong trường hợp bạn 43 (1943) được coi là năm không hợp lệ. Lý do là mktime trả về loại time_t. Loại này không thực sự được tiêu chuẩn hóa. Tài liệu cho biết:

Loại time_t là giá trị tích phân đại diện cho số giây trôi qua kể từ 00:00 giờ, ngày 1 tháng 1 năm 1970 UTC. Và tm_year là số năm kể từ năm 1900

Liên kết này What is ultimately a time_t typedef to? nói:

time_t đại diện cho số giây kể từ khi bắt đầu của Unix thời đại: nửa đêm UTC của ngày 01 Tháng 1 năm 1970 (không đếm giây nhảy vọt). Một số hệ thống xử lý chính xác các giá trị thời gian âm, trong khi các hệ thống khác làm không.

Nếu chúng ta xem xét rằng time_t là 32 bit đã ký số nguyên, trong kịch bản tốt nhất mà bạn có thể tạo ngày giữa ~ 13/12/1901 và 19/1/2038

Nhưng trong trường hợp của bạn việc triển khai không sử dụng phần phủ định của time_t, vì vậy bạn không thể tạo ngày trước năm 1970 với mktime.

+1

Thực ra, POSIX nói rằng 'time_t' là một kiểu đã ký ([link] (http://stackoverflow.com/questions/471248/what-is-ultimately-a-time-t-typedef-to)), vì vậy , khi được triển khai dưới dạng số nguyên 32 bit, nó * có thể * được sử dụng để biểu thị tối đa 68 năm trước năm 1970. –

+0

@Mat Thực sự phụ thuộc vào việc triển khai, vui lòng đọc kỹ liên kết của Matteo Italia http://stackoverflow.com/question/471248/what-is-finally-a-time-t-typedef-to. time_t đại diện cho số giây kể từ khi bắt đầu kỷ nguyên Unix: nửa đêm UTC ngày 1 tháng 1 năm 1970 (không tính giây nhảy vọt). Một số hệ thống xử lý chính xác các giá trị thời gian âm, trong khi các hệ thống khác ** không **. – benjarobin

+0

Đây không phải là do time_t được ký rằng tính toán ngày tháng trước năm 1970 được thực hiện. Vì tiêu chuẩn không nói bất cứ điều gì về điều này, sự hỗ trợ của ngày trước năm 1970 có thể không được thêm vào. – benjarobin

0

Bạn đang cố gắng trình bày ngày "ngày 2 tháng 1 năm 1943".
Trên hệ thống Unix/Linux, ngày này không thể đại diện trong giá trị time_t, bởi vì các hệ thống đó sử dụng "ngày 1 tháng 1 năm 1970" làm ngày tham chiếu.

Cập nhật:
POSIX chỉ định rằng mktime trả về thời gian trong "giây kể từ thời đại" (nơi Epoch = 01-01-1970 00:00:00). Trong một diễn giải nghiêm ngặt, các ngày trước ngày 1 tháng 1 năm 1970 có thể không được đại diện, bởi vì 'giây kể từ' vốn đã là một số dương.

ANSI/ISO C không rõ ràng về khả năng có giá trị âm cho kết quả của mktime.

+1

'time_t' được ký, năm 1943 không nằm ngoài phạm vi. – Mat

2

time_t là số nguyên 64 bit trên hệ thống của bạn và bạn đang sử dụng trình định dạng cờ định dạng sai để in ra. Bạn cần phải sử dụng modifier ll để chỉ ra rằng đó là 64 bit:

time_t t = mktime(&stm); 
printf("%lld", (int64_t)t); // This will be correct if time_t is 32 or 64 bits 

Kể từ thời điểm đó là trước khi kỷ nguyên (ngày 01 tháng một năm 1970), thời gian là một giá trị tiêu cực như -851.910.873, đó là 0xffffffffcd38df27 trong hex dưới dạng số nguyên 64 bit. Khi bạn cố gắng in ra dưới dạng số nguyên 32 bit, bạn nhận được 32 bit trên, là 0xffffffff hoặc -1 (mặc dù về mặt kỹ thuật đây là hành vi không xác định theo tiêu chuẩn C, vì vậy đừng dựa vào điều này).

Như những người khác đã đề cập, kích thước thực tế của time_t không được xác định, vì vậy bạn không nên thực hiện bất kỳ giả định về nó. Điều an toàn nhất cần làm là luôn mở rộng nó lên 64 bit nếu bạn thực sự cần biết nó lớn đến cỡ nào.

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