C语言--获取当前时间(不推荐使用gmtime)

C语言–获取当前时间

前两天写了一个获取时间的文章, 但是为什么又写一篇文章.

1、上一篇 总结的函数少.

2、遇到了问题.
有一天晚上使用gmtime函数,获取时间出现了26点的情况. 白天的时候就正常了.

2020-4-16 26:35:23
实际时间是:
2020-4-17 2:35:23

3、再次测试

baoshaohua:获取系统当前时间 bao$ ./ctime 
sec = Sun Apr 19 01:07:27 2020

str = Sun Apr 19 01:07:27 2020

baoshaohua:获取系统当前时间 bao$ ./gmtime 
2020-04-18 25:07:28
2020-04-18 25:07:28
baoshaohua:获取系统当前时间 bao$ ./localtime 
2020-04-19 01:07:30
2020-04-19 01:07:30

gmtime转出来的是0时区的标准时间, 输出时间的时候“我” +8了,

使用localtime函数获取·分解时间, 当前时区的时间.


获取系统当前时间 demo

#include 
#include 

int main(int argc, char *argv[]) {
     
    char len[20] = {
     0};

    time_t timep;
    time(&timep);

    struct tm *p;
    p = gmtime(&timep);

    snprintf(len, 20, "%d-%d-%d %d:%d:%d", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, 8 + p->tm_hour, p->tm_min, p->tm_sec);

    printf("\n%s\n", len);
    return 0;
}

运行结果:

baoshaohua:test bao$ ./test 

2020-3-25 9:51:42
baoshaohua:test bao$ 

获取系统当前时间,时间格式 yyyy-MM-dd HH:mm:ss


+++BUG+++

2020-4-16 26:35:23

实际时间是:

2020-4-17 2:35:23

+++BUG+++


在C语言中,获取日期时间的函数 不只是有这一个,还有其他几种

一、time(get time in seconds)

  • 此函数会返回从公元 1970 年 1 月 1 日的 UTC 时间从 0 时 0 分 0 秒 算起到现在所经过的秒数。

  • 如果 tloc 并非空指针的话,此函数也会将 返回值存到 tloc 指针所指的内存。

  • 参数time_t就是long

  • get time in seconds 以秒为单位获取时间

#include 
#include 

/**
 * 	#include 
 *  time_t time(time_t *tloc);   //参数是 time_t 实际是  long
 *  
 *  The time() function returns the value of time in seconds since 0 hours, 0 minutes, 0 seconds, January 1, 1970, Coordinated Universal Time, without including leap seconds. 
 */


int main(int arrgc, char const *argv[]){
     
	time_t tloc = 0;

	// time_t tt = time(NULL);
	time_t tt = time((time_t *)&tloc);

	printf("tt [%ld]\n", tt);
	printf("tloc [%ld]\n", tloc);

	return 0;
}

运行结果:

baoshaohua:test bao$ gcc -o time time.c 
baoshaohua:test bao$ ./time 
tt [1587116499]
tloc [1587116499]

1.1 小插曲

我不是定义为变量 time_t tloc = 0 ,

而是定义为指针 time_t *tloc = NULL;,

定义为变量 time_t tloc = 0 是有空间的.

定义为指针 time_t *tloc = NULL; 这个空间是指针的空间,不是变量的空间.

int main(int arrgc, char const *argv[]){
	time_t *tloc = NULL;

	time_t tt = time((time_t *)tloc);

	printf("tt [%ld]\n", tt);

	printf("tloc [%s]\n", tloc);
	printf("tloc [%ld]\n", *tloc);
}

输出为:

baoshaohua:获取系统当前时间 bao$ ./time 
tt [1587117447]
tloc [(null)]
Segmentation fault: 11

二、将日期和时间转换为分解时间或ASCII

broken-down time Calendar Time
分解时间 日历时间
tm数据类型 time_t数据类型
用time_t表示的时间(日历时间)是从一个时间点(例如:1970年1月1日…
#include 


char *asctime(const struct tm *tm);
char *asctime_r(const struct tm *tm, char *buf);


char *ctime(const time_t *timep);
char *ctime_r(const time_t *timep, char *buf);


struct tm *gmtime(const time_t *timep);
struct tm *gmtime_r(const time_t *timep, struct tm *result);


struct tm *localtime(const time_t *timep);
struct tm *localtime_r(const time_t *timep, struct tm *result);


time_t mktime(struct tm *tm);



//tm 结构体
struct tm {
            int tm_sec;    /* Seconds (0-60) */
            int tm_min;    /* Minutes (0-59) */
            int tm_hour;   /* Hours (0-23) */
            int tm_mday;   /* Day of the month (1-31) */
            int tm_mon;    /* Month (0-11) */
            int tm_year;   /* Year - 1900 */
            
            int tm_wday;   /* Day of the week (0-6, Sunday = 0) */
            int tm_yday;   /* Day in the year (0-365, 1 Jan = 0) */
            int tm_isdst;  /* Daylight saving time */
};


The members of the tm structure are:

       tm_sec    The  number  of seconds after the minute, normally in the range 0 to 59, but can be up to 60 to allow for leap
                 seconds.

       tm_min    The number of minutes after the hour, in the range 0 to 59.

       tm_hour   The number of hours past midnight, in the range 0 to 23.

       tm_mday   The day of the month, in the range 1 to 31.

       tm_mon    The number of months since January, in the range 0 to 11.

       tm_year   The number of years since 1900.

       tm_wday   The number of days since Sunday, in the range 0 to 6.

       tm_yday   The number of days since January 1, in the range 0 to 365.

       tm_isdst  A flag that indicates whether daylight saving time is in effect at the time described.  The value is  positive
                 if daylight saving time is in effect, zero if it is not, and negative if the information is not available.
  • ctime()gmtime()localtime()函数都接受数据类型time_t的参数,该参数表示日历时间。

  • asctime()mktime()函数都接受一个表示分解时间的参数,它是一个分隔为年、月、日等的表示。

  • 这四个函数asctime()ctime()gmtime()localtime()返回一个指向静态数据的指针,因此不是线程安全的。

  • gmtime_r等函数, 会将结果放在两个“地方”. 一个是返回值的, 你只需要用指针接收;
    result的那个你需要申请内存, 而不是一个tm结构体的指针.(否则,编译没问题,运行段错误)


2.1 ctime(将日历时间转换为以null结尾的字符串)

#include 
#include 
#include 

/**
 *  @brief 
 *  #include 
 *  char * ctime(const time_t *clock); 
 * 
 *  ctime()将参数 clock 所指的 time_t 结构中的信息转换成真实世界 所使用的时间日期表示方法,然后将结果以字符串形态返回。
 *  此函数已经由时区转换成当地时间,字符串格式为“Wed Jun 30 21 :49 08 1993\n”。若再调用相关的时间日期函数,此字符串可能会被破坏。
 */
int main(int argc, char *argv[]) {
     
    char str[30] = {
     0}; 
    time_t *clock;
    
    //获取时间,保存到time_t结构体中。在time的返回值(sec)里面有全部秒数
    sec = time(clock);
    strncpy(str, 32, ctime(clock)); //将time_t类型的结构体中的时间,按照一定格式保存成字符串,

    printf("str = %s\n", str);

    return 0;
}

运行结果:

baoshaohua:test bao$ gcc -o ctime ctime.c 
baoshaohua:test bao$ ./ctime 

str = Wed Mar 25 15:50:23 2020

  • 将日历时间转换为以null结尾的字符串

  • 返回值指向一个静态分配的字符串,该字符串可能会被随后对任意日期和时间函数的调用覆盖。

  • 该函数还设置了外部变量tzname、timezone和daylight.

参见tzset(3)

这种方式获取到的时间,格式是固定的,不能满足需求。

2.2 ctime_r

char *ctime_r(const time_t *timep, char *buf);

  • ctime_rctime执行相同的操作, 但将字符串存储在用户提供的缓冲区中,该缓冲区至少有26个字节的空间。

  • 不需要设置tzname, timezone, and daylight.

  • 将时间字符串保存在两处, 但是返回值的字符串你只需要传一个指针, buf需要传一个数组的首地址.

int main(int argc, char *argv[]) {
     
    int sec = 0;
    char str[30] = {
     0};
    char str1[30] = {
     0};
    time_t *clock;
    
    //获取时间,保存到time_t结构体中。在time的返回值(sec)里面有全部秒数
    sec = time(clock);
 
    strcpy(str1, ctime_r(clock, str));
    printf("sec = %s\n", str1);
    printf("str = %s\n", str);

    return 0;
}

运行结果:

baoshaohua:获取系统当前时间 bao$ ./ctime 
sec = Sat Apr 18 10:18:07 2020

str = Sat Apr 18 10:18:07 2020

3.1 gmtime(将日历时间 --> 分解时间)

#include 
#include 

/**
 * #include 
 * struct tm * gmtime(const time_t *clock);
 * 
 * gmtime()将参数 clock 所指的 time_t 结构中的信息转换成真实世界 所使用的时间日期表示方法,然后将结果由结构 tm 返回。结构 tm 的定义为:
    struct tm {
        int tm_sec;     //代表目前秒数,正常范围为 0-59,但允许至 61 秒
        int tm_min;     //代表目前分数,范围 0-59
        int tm_hour;    //从午夜算起的时数,范围为 0-23
        int tm_mday;    //目前月份的日数,范围 01-31
        int tm_mon;     //代表目前月份,从一月算起,范围从 0-11
        int tm_year;    //从 1900 年算起至今的年数
        int tm_wday;    //一星期的日数,从星期一算起,范围为 0-6
        int tm_yday;    //从今年 1 月 1 日算起至今的天数,范围为 0-365 int tm_isdst 日光节约时间的旗标 此函数返回的时间日期未经时区转换,而是 UTC 时间。
        int tm_isdst;
    };
*/


int main(int argc, char *argv[])
{
     
    time_t timep;
    time(&timep);

    struct tm *p;
    p = gmtime(&timep);

    printf("%d\n", p->tm_sec);         /*获取当前秒*/
    printf("%d\n", p->tm_min);         /*获取当前分*/
    printf("%d\n", 8 + p->tm_hour);    /*获取当前时,这里获取西方的时间,刚好相差八个小时*/
    printf("%d\n", p->tm_mday);        /*获取当前月份日数,范围是1-31*/
    printf("%d\n", 1 + p->tm_mon);     /*获取当前月份,范围是0-11,所以要加1*/
    printf("%d\n", 1900 + p->tm_year); /*获取当前年份,从1900开始,所以要加1900*/
    printf("%d\n", p->tm_yday);        /*从今年1月1日算起至今的天数,范围为0-365*/    
    return 0;
}

运行结果:

baoshaohua:获取系统当前时间 bao$ gcc -o gmtime gmtime.c 
baoshaohua:获取系统当前时间 bao$ ./gmtime 
11
37
11
18
4
2020
108

如果需要组成你需要的时间格式,那么就可以借助 snprintf 函数

3.2 gmtime_r(将日历时间 --> 分解时间)

struct tm *gmtime_r(const time_t *timep, struct tm *result);

int main(int argc, char *argv[])
{
     
    time_t timep;
    time(&timep);

    struct tm *p = NULL;
    struct tm *p1 = NULL;

    p = calloc(1, sizeof(struct tm));

    p1 = gmtime_r(&timep, p);
    
	printf("%04d-%02d-%02d %02d:%02d:%02d\n", 1900 + p->tm_year, 1 + p->tm_mon, p->tm_mday, 8 + p->tm_hour, p->tm_min, p->tm_sec);
    printf("%04d-%02d-%02d %02d:%02d:%02d\n", 1900 + p1->tm_year, 1 + p1->tm_mon, p1->tm_mday, 8 + p1->tm_hour, p1->tm_min, p1->tm_sec);


    return 0;
}

运行结果:

baoshaohua:获取系统当前时间 bao$ gcc -o gmtime gmtime.c 
baoshaohua:获取系统当前时间 bao$ ./gmtime 
2020-04-18 11:40:14
2020-04-18 11:40:14
  • p 和 p1 都有分解时间. p 是 ‘我’ 申请的空间, p1是库函数gmtime_r申请.

  • 返回值指向一个静态分配的结构,

4.1 localtime

struct tm *localtime(const time_t *timep);
struct tm *localtime_r(const time_t *timep, struct tm *result);
#include 
#include 


int main(int argc, char const *argv[]){
     
    time_t timep;

    time(&timep);

    struct tm *t = NULL;

    t = localtime(&timep);
  
    printf("%04d-%02d-%02d %02d:%02d:%02d\n", 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
    
    return 0;
}

运行结果:

baoshaohua:获取系统当前时间 bao$ gcc -o localtime localtime.c 
baoshaohua:获取系统当前时间 bao$ ./localtime 
2020-04-18 11:32:16
  • 注意和gmtime不同的是, 时间没有+8

4.2 localtime_r

int main(int argc, char const *argv[]){
     
    time_t timep;

    time(&timep);

    struct tm *t = NULL;
    struct tm t1 = {
     0};

    t = localtime_r(&timep, &t1);

    printf("%04d-%02d-%02d %02d:%02d:%02d\n", 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);
    printf("%04d-%02d-%02d %02d:%02d:%02d\n", 1900 + t1.tm_year, 1 + t1.tm_mon, t1.tm_mday, t1.tm_hour, t1.tm_min, t1.tm_sec);

    return 0;
}

运行结果:

baoshaohua:获取系统当前时间 bao$ gcc -o localtime localtime.c 
baoshaohua:获取系统当前时间 bao$ ./localtime 
2020-04-18 11:44:23
2020-04-18 11:44:23

三、将分解时间转换为日历时间

time_t mktime(struct tm *tm);

#include 
#include 

int main(int argc, char const *argv[]){
     
    time_t timep;
    time_t result;
    long sec = time(&timep);

    struct tm *t = NULL;

    t = localtime(&timep);
    printf("%04d-%02d-%02d %02d:%02d:%02d\n", 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);

    result = mktime(t);

    printf("result [%ld]\n", result);
    printf("sec [%ld]\n", sec);

    return 0;
}
baoshaohua:获取系统当前时间 bao$ gcc -o mktime mktime.c 
baoshaohua:获取系统当前时间 bao$ ./mktime 
2020-04-18 12:27:16
result [1587184036]
sec [1587184036]

三、将分解时间转换为null结尾的字符串

1、asctime

char *asctime(const struct tm *tm);
char *asctime_r(const struct tm *tm, char *buf);
#include 
#include 

int main(int argc, char const *argv[]){
     
    time_t timep;
    long sec = time(&timep);

    struct tm *t = NULL;
    char *result = NULL;

    t = localtime(&timep);
    printf("%04d-%02d-%02d %02d:%02d:%02d\n", 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);

    result = asctime(t);

    printf("result [%s]\n", result);
    printf("sec [%ld]\n", sec);

    return 0;
}

运行结果:

baoshaohua:获取系统当前时间 bao$ gcc -o asctime asctime.c 
baoshaohua:获取系统当前时间 bao$ ./asctime 
2020-04-18 12:15:09
result [Sat Apr 18 12:15:09 2020
]
sec [1587183309]
  • asctime 的返回值不需要调用者 申请空间.

2、 asctime_r

int main(int argc, char const *argv[]){
     
    time_t timep;
    long sec = time(&timep);

    struct tm *t = NULL;
    char result[32] = {
     0};

    t = localtime(&timep);
    printf("%04d-%02d-%02d %02d:%02d:%02d\n", 1900 + t->tm_year, 1 + t->tm_mon, t->tm_mday, t->tm_hour, t->tm_min, t->tm_sec);

    asctime_r(t, result);

    printf("result [%s]\n", result);
    printf("sec [%ld]\n", sec);

    return 0;
}

四、gettimeofday

#include 
#include 

/**
 * @brief 
 *  #include 
 *  int gettimeofday(struct timeval * tv, struct timezone * tz)
 * 
 *  gettimeofday () 会把目前的时间放到 tv 所指的结构返回,当地时区 的信息则放到 tz 所指的结构中。
 *  
 * struct timeval {
 *          time_t       tv_sec;   // seconds since Jan. 1, 1970 
 *          suseconds_t  tv_usec;  // and microseconds 
 *    };
 *
 */

int main(int argc, char *argv[]) {
      
    struct timeval tv;
    struct timezone tz;

    time_t * tloc;
    int sec = time((time_t *)tloc);

    printf("\n%d\n\n", sec);

    gettimeofday(&tv, NULL); 

    printf("\n\n%ld\n\n", tv.tv_sec);
    
    
    return 0;
}

运行结果:

baoshaohua:获取系统当前时间 bao$ ./gettimeofday 

1587034229



1587034229


欢迎关注公众号:
C语言--获取当前时间(不推荐使用gmtime)_第1张图片

你可能感兴趣的:(C语言,指针,字符串)