Convert snmp octet string to human readable date format

后端 未结 3 571
抹茶落季
抹茶落季 2021-02-09 02:36

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)

3条回答
  •  不知归路
    2021-02-09 03:34

    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.
    

    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)
    

    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.

    [update]

    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.

提交回复
热议问题