[英]Convert snmp octet string to human readable date format
使用pysnmp框架我得到了一些snmp walk值。 不幸的是对于oid
1.3.6.1.21.69.1.5.8.1.2(DOCS-CABLE-DEVICE-MIB)
我得到一个奇怪的结果,我无法在这里正确打印,因为它包含像BEL
ACK
一样的ascii字符
做一个repr我得到:
八位组串( '\\ X07 \\ XD8 \\吨\\ X17 \\ X03 \\ x184 \\ X00')
但输出应如下所示:
2008-9-23,3:24:52.0
格式称为“DateAndTime”。 如何将OctetString输出转换为“人类可读”的日期/时间?
您可以在此处找到格式规范。
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.
为了解码您的样本数据,您可以使用这个快速而简单的单行:
>>> 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),而时间元组[6]是微秒(0 <= x <1000000);
正确的实现留给读者练习
。
[更新]
8年后,让我们尝试解决这个问题(我是懒惰还是什么?):
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")
我不确定我的时区偏移是否正确,但我没有测试样本数据,随时修改答案或在评论中ping我。
@Paulo Scardine:这是我在解决一个非常类似的问题时在线找到的最佳答案。 即使有了这个答案,我还是花了一点时间来解决我的问题,所以我想发布一个可能会增加更多清晰度的后续答案。 (特别是具有不同长度选项的日期的问题)。
下面的代码连接到服务器并抓取系统时间,然后将其作为字符串输出以说明方法。
import netsnmp
import struct
oid = netsnmp.Varbind('hrSystemDate.0')
resp = netsnmp.snmpget(oid, Version=1, DestHost='<ip>', Community='public')
oct = str(resp[0])
# hrSystemDate can be either 8 or 11 units in length.
oct_len = len(oct)
fmt_mapping = dict({8:'>HBBBBBB', 11:'>HBBBBBBcBB'})
if oct_len == 8 or oct_len == 11:
t = struct.unpack(fmt_mapping[oct_len], oct)
print 'date tuple: %s' % (repr(t))
else:
print 'invalid date format'
我希望这有助于其他有类似问题的人尝试使用此类数据。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.