SimpleDateFormat - 日、月、时间不正确
SimpleDateFormat - day, month, time are incorrect
此代码将十六进制 (radix16) 格式的供应商专有时间戳转换为 Unix 时间。我从 Java 文档中知道 SimpleDateFormat
是从零开始的月份 (Jan=0
),但是,当使用格式字符串从 Unix 时间戳转换为人类可读格式时,月、日和时间都不正确(见末尾评论中的结果)。
预计:
Yr 2010 Mo 1 Da 4 Time 13513407 (03:45:13:407).
结果:
HR:20100205_032123239.
月份是 02
而不是 01
(正如预期的那样),但日期是 05
而不是 04
。小时 (03
) 正确,但 mins
、secs
和 millis
不正确。
我在评论中包含了用于测试的传递 "text" 值。
public static long parseUnsignedHex(String text) {
// text = "07DA010400CE32BF"
long bsUnixTs = 0;
if (text.length() == 16) {
String bsYr = text.substring(1, 4);
String bsMo = text.substring(5,6);
String bsDa = text.substring(7,8);
String bsTime = text.substring(9,16);
try {
long bsYrL = Long.decode("0x" + bsYr);
long bsMoL = Long.decode("0x" + bsMo);
long bsDaL = Long.decode("0x" + bsDa);
long bsTimeL = Long.decode("0x" + bsTime);
Calendar bsCal = Calendar.getInstance();
bsCal.set((int)bsYrL, (int)bsMoL, (int)bsDaL);
bsCal.setTimeInMillis(bsCal.getTimeInMillis() + bsTimeL);
bsUnixTs = bsCal.getTimeInMillis();
System.out.printf("Yr %d Mo %d Da %d Time %d%n", bsYrL, bsMoL, bsDaL, bsTimeL);
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (Throwable e){
e.printStackTrace();
}
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmssSSS");
// convert unix into yyyyMMdd_HHmmssSSS Human Readable (HR) format
String[][] arTimeString = new String[1][2];
for(int i=0; i<arTimeString.length; i++){
arTimeString[i][0] = Long.toString(bsUnixTs);
arTimeString[i][1] = sdf.format(bsUnixTs);
try {
System.out.format("Unix:" + arTimeString[i][0] + " HR:" + arTimeString[i][1]);
System.out.println();
// result:
// SimpleDateFormat - month is zero-based
// the day of month may be incremented because the time is 03:45:13:407
// Yr 2010 Mo 1 Da 4 Time 13513407
// Unix:1265358083239 HR:20100205_032123239
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return bsUnixTs;
}
基本上,改变...
Calendar bsCal = Calendar.getInstance();
bsCal.set((int)bsYrL, (int)bsMoL, (int)bsDaL);
bsCal.setTimeInMillis(bsCal.getTimeInMillis() + bsTimeL);
到
Calendar bsCal = Calendar.getInstance();
bsCal.set((int) bsYrL, (int) bsMoL - 1, (int) bsDaL, 0, 0);
bsCal.set(Calendar.SECOND, 0);
bsCal.set(Calendar.MILLISECOND, 0);
这将导致输出
Yr 2010 Mo 1 Da 4 Time 13513407
Unix:1262537113407 HR:20100104_034513407
Calendar
使用基于 0
的月份,而不是 SimpleDateFormat
,此外,当使用 Calendar#set
时,它只会影响您提供的字段,留下 hour
、minute
和 second
以及 millisconds
自 Calendar
创建时未变(这是 time/date 值的快照)
所以您的原始代码所做的是捕获当前日期和时间的快照,重置年、月和日值,向当前时间添加额外的时间值...
此代码将十六进制 (radix16) 格式的供应商专有时间戳转换为 Unix 时间。我从 Java 文档中知道 SimpleDateFormat
是从零开始的月份 (Jan=0
),但是,当使用格式字符串从 Unix 时间戳转换为人类可读格式时,月、日和时间都不正确(见末尾评论中的结果)。
预计:
Yr 2010 Mo 1 Da 4 Time 13513407 (03:45:13:407).
结果:
HR:20100205_032123239.
月份是 02
而不是 01
(正如预期的那样),但日期是 05
而不是 04
。小时 (03
) 正确,但 mins
、secs
和 millis
不正确。
我在评论中包含了用于测试的传递 "text" 值。
public static long parseUnsignedHex(String text) {
// text = "07DA010400CE32BF"
long bsUnixTs = 0;
if (text.length() == 16) {
String bsYr = text.substring(1, 4);
String bsMo = text.substring(5,6);
String bsDa = text.substring(7,8);
String bsTime = text.substring(9,16);
try {
long bsYrL = Long.decode("0x" + bsYr);
long bsMoL = Long.decode("0x" + bsMo);
long bsDaL = Long.decode("0x" + bsDa);
long bsTimeL = Long.decode("0x" + bsTime);
Calendar bsCal = Calendar.getInstance();
bsCal.set((int)bsYrL, (int)bsMoL, (int)bsDaL);
bsCal.setTimeInMillis(bsCal.getTimeInMillis() + bsTimeL);
bsUnixTs = bsCal.getTimeInMillis();
System.out.printf("Yr %d Mo %d Da %d Time %d%n", bsYrL, bsMoL, bsDaL, bsTimeL);
} catch (NumberFormatException e) {
e.printStackTrace();
} catch (Throwable e){
e.printStackTrace();
}
}
SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMdd_HHmmssSSS");
// convert unix into yyyyMMdd_HHmmssSSS Human Readable (HR) format
String[][] arTimeString = new String[1][2];
for(int i=0; i<arTimeString.length; i++){
arTimeString[i][0] = Long.toString(bsUnixTs);
arTimeString[i][1] = sdf.format(bsUnixTs);
try {
System.out.format("Unix:" + arTimeString[i][0] + " HR:" + arTimeString[i][1]);
System.out.println();
// result:
// SimpleDateFormat - month is zero-based
// the day of month may be incremented because the time is 03:45:13:407
// Yr 2010 Mo 1 Da 4 Time 13513407
// Unix:1265358083239 HR:20100205_032123239
} catch (Exception e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
return bsUnixTs;
}
基本上,改变...
Calendar bsCal = Calendar.getInstance();
bsCal.set((int)bsYrL, (int)bsMoL, (int)bsDaL);
bsCal.setTimeInMillis(bsCal.getTimeInMillis() + bsTimeL);
到
Calendar bsCal = Calendar.getInstance();
bsCal.set((int) bsYrL, (int) bsMoL - 1, (int) bsDaL, 0, 0);
bsCal.set(Calendar.SECOND, 0);
bsCal.set(Calendar.MILLISECOND, 0);
这将导致输出
Yr 2010 Mo 1 Da 4 Time 13513407
Unix:1262537113407 HR:20100104_034513407
Calendar
使用基于 0
的月份,而不是 SimpleDateFormat
,此外,当使用 Calendar#set
时,它只会影响您提供的字段,留下 hour
、minute
和 second
以及 millisconds
自 Calendar
创建时未变(这是 time/date 值的快照)
所以您的原始代码所做的是捕获当前日期和时间的快照,重置年、月和日值,向当前时间添加额外的时间值...