存储两个字节的日期

时间:2015-03-13 13:55:44

标签: java encoding binary

我最近看到有关二进制编码的讨论,给出的示例是将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

5 个答案:

答案 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 savingsleap seconds的天数并不总是86400000毫秒。

答案 2 :(得分:1)

如果您有两个字节ab,则可以重建原始时间戳,如下所示:

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数组中选取两个字节);
  • 然后乘以86400000以创建时间戳;
  • 使用接受时间戳的Date构造函数。

如上所述,其中一个Date构造函数接受时间戳(类型为long)作为构造Date对象的参数。为此,我们必须将双字节日期转换回完整时间戳。

请注意,由于转换,人们不能依赖小时,分钟和秒的值。所以它并不完全是原始时间戳。