linux API修改系统时间

http://t.zoukankan.com/PengfeiSong-p-6562304.html Linux 设置系统时间和日期 API
http://t.zoukankan.com/PengfeiSong-p-6562304.html Linux下时间类API

1、常用的时间相关的API和C库函数有9个:

time
ctime
localtime
gmtime
mktime
asctime
strftime
gettimeofday
settimeofday

  • 1、time系统调用返回当前时间以秒为单位的距离1970-01-01 00:00:00 +0000(UTC)过去的秒数。这个time内部就是用jiffies换算得到的秒数。其他函数基本都是围绕着time来工作的。
  • 2、gmtime和localtime会把time得到的秒数变成一个struct tm结构体表示的时间。区别是gmtime得到的是国际时间,而localtime得到的是本地(指的是你运行localtime函数的程序所在的计算机所设置的时区对应的本地时间)时间。mktime用来完成相反方向的转换(struct tm到time_t)
  • 3、如果从struct tm出发想得到字符串格式的时间,可以用asctime或者strftime都可以。(如果从time_t出发想得到字符串格式的时间用ctime即可)
  • 4、gettimeofday返回的时间是由struct timeval和struct timezone这两个结构体来共同表示的,其中timeval表示时间,而timezone表示时区。settimeofday是用来设置当前的时间和时区的。
  • 5、总结:不管用哪个系统调用,最终得到的时间本质上都是一个时间(这个时间最终都是从kernel中记录的jiffies中计算得来的),只不过不同的函数返回的时间的格式不同,精度不同
#include <stdio.h>
#include <time.h>
#include <sys/time.h>
#include <string.h>
int main(void)
{
    
    time_t tNow = 0;
    struct tm tmNow;
    char buf[100];
    struct timeval tv={0};
    struct timezone tz ={0};
    int ret = -1;
    //tNow = time(NULL);
    time(&tNow);
    if( tNow < 0)
    {
        perror("time");
        return -1;
    }    
    printf("time: %ld .
",((tNow/(60*60*24*365))+1970));
    
    printf("ctime: =%s ",ctime(&tNow));
    
    memset(&tmNow, 0 , sizeof(tmNow));
    
    gmtime_r(&tNow,&tmNow);
    printf("gmtime: %d 年%d 月 %d 日%d 时 %d 分 %d 秒 
",tmNow.tm_year+1900,tmNow.tm_mon+1,tmNow.tm_mday,tmNow.tm_hour+8,tmNow.tm_min,tmNow.tm_sec);
    
    memset(&tmNow, 0 , sizeof(tmNow));
    localtime_r(&tNow,&tmNow);
    printf("localtime: %d 年%d 月 %d 日%d 时 %d 分 %d 秒 
",tmNow.tm_year+1900,tmNow.tm_mon+1,tmNow.tm_mday,tmNow.tm_hour,tmNow.tm_min,tmNow.tm_sec);
    
    
    asctime
    printf("asctime: %s",asctime(&tmNow));
    
    //strftime
    memset(buf,0,sizeof(buf));
    strftime(buf,sizeof(buf),"%Y-%m-%d, %H-%M-%S",&tmNow);
    printf("strftime:[%s]
",buf);

    //gettimeofday
    gettimeofday(&tv,&tz);
    printf("s=%ld,us=%ld
",tv.tv_sec,tv.tv_usec);
    
    return 0;
}
1、time
	(1)time能得到一个当前时间距离标准起点时间1970-01-01 00:00:00 +0000(UTC)过去了多少秒

2、ctime
	(1)ctime可以从time_t出发得到一个容易观察的字符串格式的当前时间。
	(2)ctime好处是很简单好用,可以直接得到当前时间的字符串格式,直接打印来看。坏处是ctime的打印时间格式是固定的,没法按照我们的想法去变。
	(3)实验结果可以看出ctime函数得到的时间是考虑了计算机中的本地时间的(计算机中的时区设置)

3、gmtime和localtime
	(1)gmtime获取的时间中:年份是以1970为基准的差值,月份是0表示1月,小时数是以UTC时间的0时区为标准的小时数(北京是东8区,因此北京时间比这个时间大8)
	(2)猜测localtime和gmtime的唯一区别就是localtime以当前计算机中设置的时区为小时的时间基准,其余一样。实践证明我们的猜测是正确的。


4、mktime
	(1)从OS中读取时间时用不到mktime的,这个mktime是用来向操作系统设置时间时用的。
	
5、asctime
	(1)asctime得到一个固定格式的字符串格式的当前时间,效果上和ctime一样的。区别是ctime从time_t出发,而asctime从struct tm出发。

6、strftime
	(1)asctime和ctime得到的时间字符串都是固定格式的,没法用户自定义格式
	(2)如果需要用户自定义时间的格式,则需要用strftime。

7、gettimeofday和settimeofday
	(1)前面讲到的基于time函数的那个系列都是以秒为单位来获取时间的,没有比秒更精确的时间。
	(2)有时候我们程序希望得到非常精确的时间(譬如以us为单位),这时候就只能通过gettimeofday来实现了。

2、话不多说,直接上代码(C文件 TimeSet.c)

#include <stdio.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <time.h>
#include <linux/rtc.h>
#include <linux/capability.h>

int  SetSysDateAndTime(const char *time_str);
void SetHWClockFromSysClock(int utc);

static int  rtc_xopen(const char **default_rtc, int flags);
static void write_rtc(time_t t, int utc);

static const char *rtcname;

int main(void)
{
        const char time_str[] = "2022-12-31 23:00:00";
        SetSysDateAndTime(time_str);
        SetHWClockFromSysClock(0);

        return 0;
}

int SetSysDateAndTime(const char *time_str)
{
    struct tm  time_tm;
    struct timeval time_tv;
    time_t timep;
    int    ret;

    if(time_str == NULL)
    {
	    fprintf(stderr, "time string args invalid!\n");
	    return -1;
    }

    sscanf(time_str, "%d-%d-%d %d:%d:%d", &time_tm.tm_year, &time_tm.tm_mon, &time_tm.tm_mday, &time_tm.tm_hour, &time_tm.tm_min, &time_tm.tm_sec);
    time_tm.tm_year     -= 1900;
    time_tm.tm_mon              -= 1;
    time_tm.tm_wday     = 0;
    time_tm.tm_yday     = 0;
    time_tm.tm_isdst    = 0;

    timep = mktime(&time_tm);
    time_tv.tv_sec  = timep;
    time_tv.tv_usec = 0;

    ret = settimeofday(&time_tv, NULL);
    if(ret != 0)
    {
        fprintf(stderr, "settimeofday failed\n");
        return -2;
    }

        return 0;
}



void SetHWClockFromSysClock(int utc)
{
        struct timeval tv;

        gettimeofday(&tv, NULL);
        //if (gettimeofday(&tv, NULL))
        //      bb_perror_msg_and_die("gettimeofday() failed");
        write_rtc(tv.tv_sec, utc);
}


static int  rtc_xopen(const char **default_rtc, int flags)
{
        int rtc;

        if (!*default_rtc)
        {
                *default_rtc = "/dev/rtc";
                rtc = open(*default_rtc, flags);
                if (rtc >= 0)
                        return rtc;
                *default_rtc = "/dev/rtc0";
                rtc = open(*default_rtc, flags);
                if (rtc >= 0)
                        return rtc;
                *default_rtc = "/dev/misc/rtc";
        }

        return open(*default_rtc, flags);
}


static void write_rtc(time_t t, int utc)
{
#define RTC_SET_TIME    _IOW('p', 0x0a, struct rtc_time) /* Set RTC time    */

        struct tm tm;
        int rtc = rtc_xopen(&rtcname, O_WRONLY);

        tm = *(utc ?

        gmtime(&t) : localtime(&t));
        tm.tm_isdst = 0;

        ioctl(rtc, RTC_SET_TIME, &tm);

        close(rtc);
}

3、linux上编译并执行

### 编译源文件
gcc -o  Timeset  Timeset.c

### 执行Timeset  
./TimeSet
  • 1
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值