在 Python 中设置硬件时钟?

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2193964/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-11-04 00:01:07  来源:igfitidea点击:

Set the hardware clock in Python?

pythonlinuxhwclock

提问by Diego Sueiro

How do I set the hardware clock with Python on embedded Linux systems?

如何在嵌入式 Linux 系统上使用 Python 设置硬件时钟?

回答by zdav

Probably no easy way other than doing an os.system() call.

除了进行 os.system() 调用之外,可能没有其他简单的方法。

import os
os.system('hwclock --set %s' % date_str)

or using the 'date' command

或使用“日期”命令

import os
os.system('date -s %s' % date_str)

or if you are dying to do some c coding, wrapping the system calls with swig... but I think that would be more work than its worth.

或者如果你很想做一些 c 编码,用 swig 包装系统调用......但我认为这会比它的价值更多。

回答by Josh Kelley

Use Python's os.systemfunction to call the hwclockcommand.

使用 Python 的os.system函数调用hwclock命令。

回答by TemporalWolf

An updated version on Ubuntu 16.04:

Ubuntu 16.04 上的更新版本:

import subprocess
import shlex

subprocess.call(shlex.split("timedatectl set-ntp false"))  # May be necessary
subprocess.call(shlex.split("sudo date -s '2 OCT 2006 18:00:00'"))
subprocess.call(shlex.split("sudo hwclock -w"))

Important note: you may need to change the time/date settings to manually set (set-ntp false) or else it will immediately change it back to the current time.

重要提示:您可能需要将时间/日期设置更改为手动设置 ( set-ntp false),否则它会立即将其改回当前时间。

hwclock -wsets the hardware clock based on the current system time (set by date)

hwclock -w根据当前系统时间设置硬件时钟(由 设置date

It is required that date& hwclockare run as sudoas well.

还需要运行date& 。hwclocksudo

回答by Mathias Laurin

This uses ioctlto set the hardware clock as requested (but not the system clock). It avoids extra processes but is more involved. I am using pytzand dateutilto handle local/utc conversions. Feel free to use the code (3-clause BSD License). Get the clock with get_hwclock()and set it with set_hwclock()...

这用于ioctl根据请求设置硬件时钟(但不是系统时钟)。它避免了额外的过程,但涉及更多。我正在使用pytzdateutil处理本地/UTC 转换。随意使用代码(3 条款 BSD 许可证)。获取时钟get_hwclock()并设置它set_hwclock()...

from collections import namedtuple
from datetime import datetime
from fcntl import ioctl
import struct
from dateutil.tz import tzutc
from pytz import timezone


# From `uapi/asm-generic/ioctl.h`
_IOC_NRBITS = 8
_IOC_TYPEBITS = 8
_IOC_SIZEBITS = 14
_IOC_DIRBITS = 2

_IOC_NRMASK = (1 << _IOC_NRBITS) - 1
_IOC_TYPEMASK = (1 << _IOC_TYPEBITS) - 1
_IOC_SIZEMASK = (1 << _IOC_SIZEBITS) - 1
_IOC_DIRMASK = (1 << _IOC_DIRBITS) - 1

_IOC_NRSHIFT = 0
_IOC_TYPESHIFT = _IOC_NRSHIFT + _IOC_NRBITS
_IOC_SIZESHIFT = _IOC_TYPESHIFT + _IOC_TYPEBITS
_IOC_DIRSHIFT = _IOC_SIZESHIFT + _IOC_SIZEBITS

_IOC_NONE = 0
_IOC_WRITE = 1
_IOC_READ = 2


def _IOC(dir, type, nr, size):
    return ((dir << _IOC_DIRSHIFT) |
            (type << _IOC_TYPESHIFT) |
            (nr << _IOC_NRSHIFT) |
            (size << _IOC_SIZESHIFT))


def _IOC_TYPECHECK(t):
    return len(t)


def _IO(type, nr):
    return _IOC(_IOC_NONE, type, nr, 0)


def _IOR(type, nr, size):
    return _IOC(_IOC_READ, type, nr, _IOC_TYPECHECK(size))


def _IOW(type, nr, size):
    return _IOC(_IOC_WRITE, type, nr, _IOC_TYPECHECK(size))


def to_utc(dtobj):
    if dtobj.tzinfo is None:
        dtobj = timezone("UTC").localize(
            dtobj.replace(tzinfo=None) - tzlocal().utcoffset(dtobj))
    return dtobj.astimezone(timezone("UTC"))


class RtcTime(namedtuple(
    # man(4) rtc
    "RtcTime",
    "tm_sec tm_min tm_hour "
    "tm_mday tm_mon tm_year "
    "tm_wday tm_yday tm_isdst"  # Last row is unused.
)):

    _fmt = 9 * "i"

    def __new__(cls, tm_sec=0, tm_min=0, tm_hour=0,
                tm_mday=0, tm_mon=0, tm_year=0,
                tm_wday=0, tm_yday=0, tm_isdst=0):
        return super(RtcTime, cls).__new__(cls, tm_sec, tm_min, tm_hour,
                                            tm_mday, tm_mon, tm_year,
                                            tm_wday, tm_yday, tm_isdst)

    def __str__(self):
        return self.to_datetime().isoformat()

    @classmethod
    def from_datetime(cls, dtobj):
        dt = to_utc(dtobj)
        return cls(tm_sec=dt.second, tm_min=dt.minute, tm_hour=dt.hour,
                   tm_mday=dt.day, tm_mon=dt.month - 1, tm_year=dt.year - 1900)

    def to_datetime(self):
        # From `hwclock.c`.
        return datetime(
            year=self.tm_year + 1900, month=self.tm_mon + 1, day=self.tm_mday,
            hour=self.tm_hour, minute=self.tm_min, second=self.tm_sec,
            tzinfo=tzutc())

    def pack(self):
        return struct.pack(self._fmt, *self)

    @classmethod
    def unpack(cls, buffer):
        return cls._make(struct.unpack(cls._fmt, buffer))


# From `uapi/linux/rtc.h`
rtc_time = RtcTime().pack()
RTC_RD_TIME = _IOR(ord("p"), 0x09, rtc_time)   # 0x80247009
RTC_SET_TIME = _IOW(ord("p"), 0x0a, rtc_time)  # 0x4024700a
del rtc_time


def get_hwclock(devrtc="/dev/rtc"):
    with open(devrtc) as rtc:
        ret = ioctl(rtc, RTC_RD_TIME, RtcTime().pack())
    return RtcTime.unpack(ret).to_datetime()


def set_hwclock(dt, devrtc="/dev/rtc"):
    with open(devrtc) as rtc:
        ioctl(rtc, RTC_SET_TIME, RtcTime.from_datetime(dt).pack())