Làm cách nào để lấy thời gian hiện tại tính bằng mili giây từ C trong Linux?


86

Làm cách nào để tính thời gian hiện tại trên Linux tính bằng mili giây?

Câu trả lời:


100

Điều này có thể đạt được bằng cách sử dụng chức năng POSIXclock_gettime .

Trong phiên bản hiện tại của POSIX, gettimeofdayđược đánh dấulỗi thời . Điều này có nghĩa là nó có thể bị xóa khỏi phiên bản trong tương lai của thông số kỹ thuật. Người viết ứng dụng được khuyến khích sử dụng clock_gettimechức năng thay vì gettimeofday.

Đây là một ví dụ về cách sử dụng clock_gettime:

#define _POSIX_C_SOURCE 200809L

#include <inttypes.h>
#include <math.h>
#include <stdio.h>
#include <time.h>

void print_current_time_with_ms (void)
{
    long            ms; // Milliseconds
    time_t          s;  // Seconds
    struct timespec spec;

    clock_gettime(CLOCK_REALTIME, &spec);

    s  = spec.tv_sec;
    ms = round(spec.tv_nsec / 1.0e6); // Convert nanoseconds to milliseconds
    if (ms > 999) {
        s++;
        ms = 0;
    }

    printf("Current time: %"PRIdMAX".%03ld seconds since the Epoch\n",
           (intmax_t)s, ms);
}

Nếu mục tiêu của bạn là đo thời gian đã trôi qua và hệ thống của bạn hỗ trợ tùy chọn "đồng hồ đơn âm", thì bạn nên cân nhắc sử dụng CLOCK_MONOTONICthay vì CLOCK_REALTIME.


7
+1 vì hoàn toàn đúng - nhưng câu trả lời của bạn có đơn vị sai. OP không muốn thời gian bằng mili giây mà là thời gian bằng mili giây.
ăn cắp vặt vào

5
Giải pháp tốt nhưng đừng quên -lm trong gcclệnh của bạn .
David Guyon

2
theo manpage cho round, bạn muốn sử dụng lround khi gán kết quả cho một số nguyên (hoặc long)
hildred

2
Bạn cần sử dụng floor () thay vì round () để nó không bao giờ làm tròn lên đến 1000 ms. Nếu không, bạn sẽ cần phải tăng skhi điều này xảy ra. Có lẽ là một sự kiện hiếm nhưng chữ số thừa có thể gây ra rắc rối.
Mike

1
@Mike Bắt đẹp. Ở mức một phần hai nghìn, nó thậm chí không hiếm như vậy, vì vậy chắc chắn nên được sửa. Thay vì sử dụng sàn, tôi nghĩ rằng tôi muốn duy trì một độ chính xác ít hơn và tiếp tục lọt vào vòng, nhưng tăng bộ đếm thứ hai nếu nó vòng lên đến 1000.
Dan Molding

58

Bạn phải làm một cái gì đó như sau:

struct timeval  tv;
gettimeofday(&tv, NULL);

double time_in_mill = 
         (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000 ; // convert tv_sec & tv_usec to millisecond

33

Sau đây là hàm dùng để lấy dấu thời gian hiện tại tính bằng mili giây:

#include <sys/time.h>

long long current_timestamp() {
    struct timeval te; 
    gettimeofday(&te, NULL); // get current time
    long long milliseconds = te.tv_sec*1000LL + te.tv_usec/1000; // calculate milliseconds
    // printf("milliseconds: %lld\n", milliseconds);
    return milliseconds;
}

Về múi giờ :

gettimeofday () hỗ trợ để chỉ định múi giờ, tôi sử dụng NULL , bỏ qua múi giờ, nhưng bạn có thể chỉ định múi giờ, nếu cần.


@Update - múi giờ

Vì việc longbiểu diễn thời gian không liên quan hoặc bị ảnh hưởng bởi chính múi giờ, vì vậy việc đặt tztham số của gettimeofday () là không cần thiết, vì nó sẽ không tạo ra bất kỳ sự khác biệt nào.

Và, theo trang mangettimeofday() , việc sử dụng timezonecấu trúc đã lỗi thời, do đó tzđối số thường phải được chỉ định là NULL, để biết chi tiết, vui lòng kiểm tra trang man.


1
> gettimeofday () hỗ trợ để chỉ định múi giờ, tôi sử dụng NULL, bỏ qua múi giờ, nhưng bạn có thể chỉ định múi giờ, nếu cần. Bạn sai rồi. Múi giờ nên được giới thiệu độc quyền thông qua cuộc gọi tới localtime ().
importanty.v.ch

@ importanty.v.ch Tôi đã làm một bài kiểm tra, vượt qua thông tzsố gettimeofday()như &(struct timezone tz = {480, 0})sẽ không nhận được bất kỳ cảnh báo nào và nó không có bất kỳ ảnh hưởng nào đến kết quả, điều đó có ý nghĩa, vì longbiểu diễn thời gian không liên quan hoặc ảnh hưởng đến theo múi giờ, phải không?
Eric Wang

Không có lý do gì để làm bất kỳ bài kiểm tra nào. Nhân Linux không có thông tin thích hợp về múi giờ, đồng thời không có cách cung cấp thông tin đó. Đó là lý do tại sao đối số tz được xử lý theo cách rất cụ thể. đại diện dài không thành vấn đề.
importanty.v.ch

@ importanty.v.ch Tại một thời điểm cụ thể, biểu thị dài không thay đổi do múi giờ, đó là lý do tại sao điều đó quan trọng và do đó thông thường chỉ NULLgiá trị hợp lý mới được vượt qua. Và, tôi tin rằng thử nghiệm luôn là một cách tiếp cận tốt để chứng minh mọi thứ.
Eric Wang


7

C11 timespec_get

Nó trả về tối đa nano giây, được làm tròn đến độ phân giải của quá trình triển khai.

Nó đã được triển khai trong Ubuntu 15.10. API trông giống như POSIX clock_gettime.

#include <time.h>
struct timespec ts;
timespec_get(&ts, TIME_UTC);
struct timespec {
    time_t   tv_sec;        /* seconds */
    long     tv_nsec;       /* nanoseconds */
};

Thêm chi tiết tại đây: https://stackoverflow.com/a/36095407/895245


0

Bắt nguồn từ câu trả lời POSIX của Dan Moulding, điều này sẽ hoạt động:

#include <time.h>
#include <math.h>

long millis(){
    struct timespec _t;
    clock_gettime(CLOCK_REALTIME, &_t);
    return _t.tv_sec*1000 + lround(_t.tv_nsec/1.0e6);
}

Cũng như được chỉ ra bởi David Guyon: biên dịch với -lm

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.