将snmp八位位组字符串转换为人类可读的日期格式 [英] Convert snmp octet string to human readable date format
问题描述
使用pysnmp框架,我在进行snmp漫游时获得了一些值。不幸的是
Using the pysnmp framework i get some values doing a snmp walk. Unfortunately for the oid
1.3.6.1.21.69.1.5.8.1.2(DOCS-CABLE-DEVICE-MIB)
1.3.6.1.21.69.1.5.8.1.2 (DOCS-CABLE-DEVICE-MIB)
我得到一个奇怪的结果,由于它包含ascii字符,如 BEL
,因此我无法在此处正确打印 ACK
i get a weird result which i cant correctly print here since it contains ascii chars like BEL
ACK
在执行一次重复时,我得到:
When doing a repr i get:
OctetString('\x07\xd8\t\x17\x03\x184\x00')
OctetString('\x07\xd8\t\x17\x03\x184\x00')
但输出应类似于:
2008-9-23,3:24:52.0
2008-9-23,3:24:52.0
该格式称为 DateAndTime。我如何将OctetString输出转换为人类可读的日期/时间?
the format is called "DateAndTime". How can i translate the OctetString output to a "human readable" date/time ?
推荐答案
您可以找到格式说明此处。
You can find the format specification here.
A date-time specification.
field octets contents range
----- ------ -------- -----
1 1-2 year* 0..65536
2 3 month 1..12
3 4 day 1..31
4 5 hour 0..23
5 6 minutes 0..59
6 7 seconds 0..60
(use 60 for leap-second)
7 8 deci-seconds 0..9
8 9 direction from UTC '+' / '-'
9 10 hours from UTC* 0..13
10 11 minutes from UTC 0..59
* Notes:
- the value of year is in network-byte order
- daylight saving time in New Zealand is +13 For example,
Tuesday May 26, 1992 at 1:30:15 PM EDT would be displayed as:
1992-5-26,13:30:15.0,-4:0
Note that if only local time is known, then timezone
information (fields 8-10) is not present.
为了解码示例数据,您可以使用以下这种简单又脏的单线: / p>
In order to decode your sample data you can use this quick-and-dirty one-liner:
>>> import struct, datetime
>>> s = '\x07\xd8\t\x17\x03\x184\x00'
>>> datetime.datetime(*struct.unpack('>HBBBBBB', s))
datetime.datetime(2008, 9, 23, 3, 24, 52)
上面的示例远非完美,它没有考虑大小(此对象的大小可变),并且缺少时区信息。还应注意,字段7是分秒(0..9),而timetuple [6]是微秒(0< = x< 1000000); 正确的实现留给读者练习。
The example above is far from perfect, it does not account for size (this object has variable size) and is missing timezone information. Also note that the field 7 is deci-seconds (0..9) while timetuple[6] is microseconds (0 <= x < 1000000); the correct implementations is left as an exercise for the reader.
[更新]
8年后,让我们尝试解决此问题(我是懒还是什么?):
8 years later, lets try to fix this answer (am I lazy or what?):
import struct, pytz, datetime
def decode_snmp_date(octetstr: bytes) -> datetime.datetime:
size = len(octetstr)
if size == 8:
(year, month, day, hour, minutes,
seconds, deci_seconds,
) = struct.unpack('>HBBBBBB', octetstr)
return datetime.datetime(
year, month, day, hour, minutes, seconds,
deci_seconds * 100_000, tzinfo=pytz.utc)
elif size == 11:
(year, month, day, hour, minutes,
seconds, deci_seconds, direction,
hours_from_utc, minutes_from_utc,
) = struct.unpack('>HBBBBBBcBB', octetstr)
offset = datetime.timedelta(
hours=hours_from_utc, minutes=minutes_from_utc)
if direction == b'-':
offset = -offset
return datetime.datetime(
year, month, day, hour, minutes, seconds,
deci_seconds * 100_000, tzinfo=pytz.utc) + offset
raise ValueError("The provided OCTETSTR is not a valid SNMP date")
我不确定时区偏移量是否正确,但我不知道有示例数据可以测试,可以随时修改答案或在评论中查验我。
I'm not sure I got the timezone offset right but I don't have sample data to test, feel free to amend the answer or ping me in the comments.
这篇关于将snmp八位位组字符串转换为人类可读的日期格式的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!