Linux C语言 19-时间获取
本节关键字:Linux、C语言、时间、随机数、获取毫秒
相关C库函数:time、localtime、rand、srand、printf
计算机时间的由来
UNIX操作系统根据计算机产生的年代和应用采用1970年1月1日作为UNIX的纪元时间,1970年1月1日0点作为计算机表示时间的是中间点,将从1970年1月1日开始经过的秒数用一个整数存放,这种高效简洁的时间表示方法被称为“Unix时间纪元”,向左和向右偏移都可以得到更早或者更后的时间。
在实际开发中,对日期和时间的操作场景非常多,例如程序启动和退出的时间,程序执行任务的时间,数据生成的时间,数据处理的各环节的时间等,无处不在。
在学习时间之前,请把Linux操作系统的时区设置为中国上海时间。
相关库函数
时间获取
#include <time.h>
// 返回自大纪元1970-01-01 00:00:00+0000(UTC)以来的秒数。如果t不是NULL,则返回值也存储在t指向的内存中。成功时,返回自Epoch以来的时间值(以秒为单位)。出现错误时,将返回((time_t)-1),并适当设置errno。
time_t time(time_t *t);
// 将秒数值转化为本地时间的结构体描述
struct tm *localtime(const time_t *timep);
// 将秒数值转换为表单的以NULL结尾的字符串
char *ctime(const time_t *timep);
struct tm
{
int tm_sec; /* seconds 0到59 */
int tm_min; /* minutes 0到59 */
int tm_hour; /* hours 0到23 */
int tm_mday; /* day of the month 0到31 */
int tm_mon; /* month 0到11 */
int tm_year; /* year 自1900年以来的年数 */
int tm_wday; /* day of the week 自周日以来的天数 0到6 */
int tm_yday; /* day in the year 自1月1日以来的天数 0到365 */
int tm_isdst; /* daylight saving time 该值为正,夏令时有效;该值为0夏令时无效;该值为tive,信息不可用 */
};
随机数
#include <stdlib.h>
// 设置随机数种子,只需设置依次即可,一般以时间作为种子
void srand(unsigned int seed);
// 获取一个随机数
int rand(void);
API使用示例
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main()
{
int i;
time_t sec;
time_t sec_rc;
sec_rc = time(&sec);
printf("sec=%d, sec_rc=%d\n", sec, sec_rc);
sec = 0;
sec = time(0);
printf("sec=%d\n", sec);
char *sTimep = NULL;
struct tm *ptime = NULL;
ptime = localtime(&sec);
printf("%04u年%02u月%02u日 %02u时%02u分%02u秒\n",
ptime->tm_year+1900,ptime->tm_mon+1, ptime->tm_mday,
ptime->tm_hour, ptime->tm_min, ptime->tm_sec );
sTimep = ctime(&sec);
printf("sTimep: %s\n", sTimep);
printf("未设置随机种子\n");
for (i=0; i<5; i++)
printf("rand=%d\n", rand());
printf("设置一次随机种子\n");
srand((unsigned int)time(0));
for (i=0; i<5; i++)
printf("rand=%d\n", rand());
printf("设置多次随机种子\n");
for (i=0; i<5; i++)
{
srand((unsigned int)time(0));
printf("rand=%d\n", rand());
}
// 获取m到n之间的随机数 rand() % n + m
printf("获取1到100之间的随机数\n");
for (i=0; i<20; i++)
printf("%d ", rand() % 100 + 1);
printf("\n");
return 0;
}
/** 运行结果:
sec=1700211276, sec_rc=1700211276
sec=1700211276
2023年11月17日 16时54分36秒
sTimep: Fri Nov 17 16:54:36 2023
未设置随机种子
rand=1804289383
rand=846930886
rand=1681692777
rand=1714636915
rand=1957747793
设置一次随机种子
rand=359111267
rand=609384155
rand=1676377208
rand=120486859
rand=1211057934
设置多次随机种子
rand=359111267
rand=359111267
rand=359111267
rand=359111267
rand=359111267
获取1到100之间的随机数
56 9 60 35 40 55 1 20 4 14 8 94 97 20 22 68 11 9 12 41
*/
本节彩蛋 适配Windows和Unix
微秒定时器
void usleep(unsigned long usec)
{
#if defined (WIN32)
Sleep(usec / 1000);
#elif defined (__unix)
struct timeval tv;
while (1)
{
tv.tv_sec = usec / 1000000;
tv.tv_usec = usec % 1000000;
if (select(0, 0, 0, 0, &tv) < 0)
{
if (getLastError() == EINTR)
{
usec = usec / 2;
if(usec >= 50000)
continue;
}
}
break;
}
#endif
}
获取精确到毫秒的时间
typedef struct {
int tm_year;
int tm_mon;
int tm_day;
int tm_hour;
int tm_min;
int tm_sec;
int tm_msec;
} tm_msec;
tm_msec *get_curtime()
{
static tm_msec tm;
#ifdef __unix
struct timeval tmptimeval;
gettimeofday(&tmptimeval,NULL);
tm.tm_sec = tmptimeval.tv_sec;
tm.tm_msec = tmptimeval.tv_usec/1000;
#endif
#ifdef _WIN32
tm.tm_sec = (time_t)time(NULL);
SYSTEMTIME systime;
::GetSystemTime(&systime);
tm.tm_msec = systime.wMilliseconds;
#endif
time_t tnow = time(0);
struct tm *ptm = localtime(&tnow);
tm.tm_year = ptm->tm_year+1900;
tm.tm_mon = ptm->tm_mon+1;
tm.tm_day = ptm->tm_mday;
tm.tm_hour = ptm->tm_hour;
tm.tm_min = ptm->tm_min;
tm.tm_sec = ptm->tm_sec;
return &tm;
}