原始blog:http://blog.csdn.net/byalc/article/details/486927
由于原作者是基于c++的,我稍作修改,改为JAVA版的.
DateAndTime是Snmpv2中的一种数据类型,它主要提供了对日期时间的描述。我在使用Snmp4j开发包时,发现其不提供对DateAndTime类型的支持,而有时又需要用到该类型,于是,自己写了一个方法解析该类型,可以实现对DateAndTime类型的格式化,并且可以方便地提取各时间项。
下面是RFC中对DateAndTime的定义:
DateAndTime ::= OCTET STRING (SIZE (8 | 11))
-- A date-time specification for the local time of day.
-- This data type is intended to provide a consistent
-- method of reporting date information.
--
-- field octets contents range
-- _____ ______ ________ _____
-- 1 1-2 year 0..65536
-- (in network byte order)
-- 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 "+" / "-"
-- (in ascii notation)
-- 9 10 hours from UTC 0..11
-- 10 11 minutes from UTC 0..59
--
-- Note that if only local time is known, then
-- timezone information (fields 8-10) is not present.
由定义可见,DateAndTime仍然是OCTET STRING类型的数据,只是对每个字节进行了具体的定义。比如前两个字节表示年,第五个字节表示小时等。所以如果某个开发包中没有DateAndTime类型,那么大可以用Octet类型去代替。但是这样做得到的只是一些无意义的乱码而已。因此,实现的关键就在于按照定义对特殊的Octet数据进行正确的解析。
既然DateAndTime也是Octet String,那么我们就可以按照字节数组来处理他。
import java.util.Vector;
import org.apache.log4j.Logger;
import org.snmp4j.CommandResponderEvent;
import org.snmp4j.PDU;
import org.snmp4j.smi.OctetString;
import org.snmp4j.smi.Variable;
import org.snmp4j.smi.VariableBinding;
import com.asb.mediation.snmp.SNMPManager;
import com.asb.mediation.util.INMSLog;
public class SNMPAdapter extends SNMPManager{
private Logger adapterlog = INMSLog.getInstance().getAdapterLog();
private Logger recvlog = INMSLog.getInstance().getReceiveLog();
public SNMPAdapter(String snmpIP, String snmpPort){
super(snmpIP, snmpPort);
}
@Override
protected void notifyMsg(CommandResponderEvent event) {
adapterlog.info("Mapper::notifyMsg>> =====NOTIFY_ALARM=====");
PDU pdu = event.getPDU();
Vector vec = pdu.getVariableBindings();
adapterlog.info("YYWifiMapper::process>> oid size = " + vec.size());
for (int i = 0; i < vec.size(); i++) {
String oidNameValue = "";
VariableBinding vb = (VariableBinding)vec.get(i);
if (vb.getVariable() instanceof OctetString) {
String value = new String(((OctetString)vb.getVariable()).getValue());
if(vb.getOid().toString().trim().equals("1.3.6.1.4.1.88888.2") ){
oidNameValue = "OID:"+vb.getOid()+"\t"+"value:" + parseDateAndTime(vb.getVariable());
}
else{
oidNameValue = "OID:"+vb.getOid()+"\t"+"value:" + value.trim();
}
}
else{
//略
}
}
}
public String parseDateAndTime(Variable v){
adapterlog.info("YYWifiMapper::parseDateAndTime>> v="+v);
// adapterlog.info("YYWifiMapper::parseDateAndTime>> v string="+v.toString());
OctetString oct = (OctetString)v;
// adapterlog.info("YYWifiMapper::parseDateAndTime>> v hex="+ oct.toHexString());
byte[] bts = oct.getValue();
byte[] format_str = new byte[128]; //保存格式化过后的时间字符串
int year;
int month;
int day;
int hour;
int minute;
int second;
int msecond;
// for(byte b:bts){
// adapterlog.info("YYWifiMapper::parseDateAndTime>> bts:"+b);
// }
year=bts[0]*256+256+bts[1]; //adapterlog.info("YYWifiMapper::parseDateAndTime>> year:"+year);
month=bts[2];
day=bts[3];
hour=bts[4];
minute=bts[5];
second=bts[6];
msecond=bts[7];
//以下为格式化字符串
int index=3;
int temp=year;
for(; index>=0; index--){
format_str[index]=(byte)(48+(temp-temp/10*10));
temp/=10;
}
format_str[4]='-';
index=6;
temp=month;
for(; index>=5; index--){
format_str[index]=(byte)(48+(temp-temp/10*10));
temp/=10;
}
format_str[7]='-';
index=9;
temp=day;
for(; index>=8; index--){
format_str[index]=(byte)(48+(temp-temp/10*10));
temp/=10;
}
format_str[10]=' ';
index=12;
temp=hour;
for(; index>=11; index--){
format_str[index]=(byte)(48+(temp-temp/10*10));
temp/=10;
}
format_str[13]=':';
index=15;
temp=minute;
for(; index>=14; index--){
format_str[index]=(byte)(48+(temp-temp/10*10));
temp/=10;
}
format_str[16]=':';
index=18;
temp=second;
for(; index>=17; index--){
format_str[index]=(byte)(48+(temp-temp/10*10));
temp/=10;
}
// format_str[19]='.';
// index=21;
// temp=msecond;
// for(; index>=20; index--){
// format_str[index]=(byte)(48+(temp-temp/10*10));
// temp/=10;
// }
//
// format_str[22]=0;
// adapterlog.info("YYWifiMapper::parseDateAndTime>> format_str = " + new String(format_str));
return new String(format_str);
}
}
实际运行log如下(注意值为16进制):
YYWifiMapper::parseDateAndTime>> v=07:dc:09:17:11:01:1b:02:2b:08:00
YYWifiMapper::parseDateAndTime>> format_str = 2012-09-23 17:01:27
处理年的时候稍有不同,因为年是由两个字节表示,所以要用高位字节乘256再加低位字节,处理语句为year=bts[0]*256+256+bts[1];标准的时间输出格式应该为YYYY-MM-DD HH:MM:SS形式。
其实自己用计算器就能算出时间,很简单了。
主要是年的计算byte是可以为负值,所以手动计算的公式:
07*256 + dc = 07*256 + 220 = 2012年;或者07*256 + (256 + dc) = 07*256 + (256 + (-36)) = 2012年;
09 = 09月
17 = 23日
11 = 17时
01 = 01分
1b = 27秒