我最近看到有关二进制编码的讨论,给出的示例是将Java Date
对象的日期部分(日,月和年)存储为两个字节。我现在正试图理解谈话中的代码片段:
long time = new Date().getTime(); // time in ms since epoch
time /= 86400000; // ms in a day
byte a = (byte)(time >>> 8);
byte b = (byte)(time);
现在我缺少的是它显然是如何简单的"将这两个字节转回原始日期的日期,月份和年份。如果我们将原始时间值保留为一个字节,我也不确定为什么我们使用两个字节。
有人可以解释一下这是怎么回事吗?我理解上面的代码在做什么,而不是如何恢复原始日期。
更新
这是谈话,有问题的幻灯片是20/21
http://www.slideshare.net/jtdavies/turn-your-xml-into-binary-java-one-2014
答案 0 :(得分:4)
假设您的byte
是8位字节,则提供16位范围或0-65535
。
日期编号可以是1-31
,可以容纳5位。
月份数可以是1-12
,可以容纳4位。
这会留下16-5-4=7
位来存储年份或0-127
的范围。您可以假设我们正在讨论2000
以后您可以轻松地将任何日期打包成16位数字。
int date = ((((y % 100) << 5) + m) << 4) + d;
int year = 2000 + (date >>> (5 + 4));
int month = (date >> 4) & 0x1f;
int day = date & 0xf;
警告 - 这个想法耗费了全球数十亿美元(据称)。它只被称为y2k bug,当时我们只添加了1900
。
答案 1 :(得分:3)
以下是如何从字节中恢复日期:
long time = new Date().getTime(); // time in ms since epoch
time /= 86400000; // ms in a day
byte a = (byte) (time >>> 8);
byte b = (byte) (time);
time = a;
time = time << 8;
time = time | b;
time *= 86400000;
System.out.println(new Date(time));
但遗憾的是,这并不总是有效,因为daylight savings和leap seconds的天数并不总是86400000毫秒。
答案 2 :(得分:1)
如果您有两个字节a
和b
,则可以重建原始时间戳,如下所示:
public static Date reconstructFromBytes(byte a, byte b) {
long timestampRecovered = (a << 8);
timestampRecovered += b;
timestampRecovered *= 86400000;
return new Date(timestampRecovered);
}
正如其中一位评论者所说,这假设一天有86400000毫秒。
答案 3 :(得分:0)
我希望这会有所帮助:
long time = new Date().getTime(); // time in ms since epoch
int days = (int) (time / 86400000); // number of days since 1970-01-01
System.out.println("Number of days since epoch: " + days);
System.out.println("As hex: " + Integer.toHexString(days));
byte a = (byte)(days >>> 8); // get higher byte
byte b = (byte)(days); // get lower byte
System.out.println("Hihger byte: " + Integer.toHexString(a));
System.out.println("Lower byte: " + Integer.toHexString(b));
打印
Number of days since epoch: 16507
As hex number: 407b
Hihger byte: 40
Lower byte: 7b
答案 4 :(得分:0)
您正在谈论的幻灯片尝试通过将数据保存为消耗更少字节的格式来减少磁盘或带宽使用。
幻灯片提供了以下代码示例:
long time = new Date().getTime(); // time in ms since epoch
time /= 86400000; // ms in a day
byte a = (byte)(time >>> 8);
byte b = (byte)(time);
该代码段的作用实际上如下:
Date
; 86400000
,因为这是一天中的毫秒数,而且我们不需要任何其他信息&#39;较小的&#39;比天; data
的数组的第8和第9位。通过这种方式,他们会删除一些他们不需要的信息;在这种情况下,所有时间单位小于一天(小时,分钟等等)。
我们可以将它保存到short
,这是两个字节:
short ourTime = (short) time;
但由于example on the slides使用byte[]
,因此会将两个字节移至data
的第8位和第9位。
从这两个字节恢复日期恰恰相反:
wordFromBytesFromOffset(8)
完成,从data
数组中选取两个字节); Date
构造函数。如上所述,其中一个Date
构造函数接受时间戳(类型为long
)作为构造Date
对象的参数。为此,我们必须将双字节日期转换回完整时间戳。
请注意,由于转换,人们不能依赖小时,分钟和秒的值。所以它并不完全是原始时间戳。