as3十六进制值到时间戳从十六进制转换为MS-DOS:32位十六进制值十进制

时间:2014-07-29 18:08:44

标签: actionscript-3 datetime hex dos

我试图理解如何将MS-DOS:32位格式的十六进制值转换/解码为人类可读日期&时间。我找到了一种方法,使用Unix十六进制时间戳/纪元到正常日期,但与我的十六进制值不同的是MS-DOS:32位格式。有人有主意吗?

var hex = "38BFFD44";
var decimal = parseInt (hex, 16);
var date = new Date(decimal*1000);
trace(date);

应输出:

Tue Jul 29 23:57:48 GMT+0000 2014

但输出日期:

Fri Mar 3 17:58:28 GMT+0000 2000

我已尝试将补偿添加到日期的秒数偏移量,但这不起作用,最终会导致错误的时间和增加天数。我确定它与十进制转换有关吗?:

date.seconds += 1402677061;

我一直在阅读更多关于MS转换的信息:DOS 32位,并在“EnCase Computer Forensics - 官方EnCE:EnCase认证审查员”

中找到了这一段

“要正确组合并计算此值,您必须按以下顺序将十六进制值输入科学计算器:00 12 00 03.这会将存储的值转换为小端。此结果的十进制值为此起始集群世界是1,179,651。“

所以我制作了一个脚本来复制它,但似乎仍然没有效果......

function toDec(n:*, endianness: * = null): String {

    var bigEndian: Boolean;
    if (endianness == null) {
        endianness = Endian.BIG_ENDIAN;
    }
    if (endianness is Boolean) {
        bigEndian = Boolean(endianness);
    } else {
        bigEndian = endianness == Endian.BIG_ENDIAN;
    }

    var string: String = n.toUpperCase();

    if (!bigEndian) {
        var i: int = 0;
        var reversed: Array = [];
        while (i < string.length) {
            var byte: String = string.charAt(i++) + string.charAt(i++);
            reversed.unshift(byte);
        }
        string = reversed.join("");
    }

    return string;
}

var hex = "38BFFD44";
var sdecimal = parseInt(toDec(hex,Endian.LITTLE_ENDIAN), 16);
var sdate = new Date(sdecimal);    

var bdecimal = parseInt(toDec(hex,Endian.BIG_ENDIAN), 16);
var bdate = new Date(bdecimal);

trace("small_endian.decimal = "+sdecimal);
trace("big_endian.decimal   = "+bdecimal);
trace("small_endian.date    = "+sdate);
trace("big_endian.date      = "+bdate);

输出:

small_endian.decimal = 1157480248
big_endian.decimal   = 952106308
small_endian.date    = Wed Jan 14 09:31:20 GMT+0000 1970
big_endian.date      = Mon Jan 12 00:28:26 GMT+0000 1970

1 个答案:

答案 0 :(得分:2)

使用MS-DOS,时间戳的每个部分都在32位时间戳的特定位内进行编码。

这是一个exFAT时间戳:

╔═══════╦══════╦═════════════════════════════╦══════════════════════════════════╗
║ Bits  ║ Size ║         Description         ║             Comments             ║
╠═══════╬══════╬═════════════════════════════╬══════════════════════════════════╣
║ 0-4   ║    5 ║ Seconds (2-second interval) ║ 0..29 (29 represents 58 seconds) ║
║ 5-10  ║    6 ║ Minutes                     ║ 0..59                            ║
║ 11-15 ║    5 ║ Hour                        ║ 0..23                            ║
║ 16-20 ║    5 ║ Day                         ║ 1..31                            ║
║ 21-24 ║    4 ║ Month                       ║ 1..12                            ║
║ 25-31 ║    7 ║ Year (as offset from 1980)  ║ 0 represents 1980                ║
╚═══════╩══════╩═════════════════════════════╩══════════════════════════════════╝

这是两个WORDS的结构(每个WORD是一个16位无符号整数) - FatDate和FatTime,如DosDateTimeToFileTime中所示:

BOOL WINAPI DosDateTimeToFileTime(
  _In_   WORD wFatDate,
  _In_   WORD wFatTime,
  _Out_  LPFILETIME lpFileTime
);

将此十六进制值解析为ActionScript date作为时间戳,因为epoch无法正常工作。

此外,还有一个字节序问题。该值必须是小端。

将0x38BFFD44从big endian(952106308)转换为little endian(1157480248)产生了预期的输出。

在ActionScript中,这应该是:

var t:uint = 1157480248; // 0x38BFFD44 as little endian;

var date:Date = new Date(
    1980 + ((t & 0xfe000000) >> 25), // year
    ((t & 0x1e00000) >> 21) - 1,     // month
    ((t & 0x1f0000) >> 16),          // day
    ((t & 0xf800) >> 11),            // hour
    ((t & 0x7e0) >> 5),              // minute
    2 * (t & 0x1f)                   // second
    );

输出:

  

Tue Jul 29 23:57:48 GMT-0500 2014

您必须考虑UTC的时区偏移。

参考文献: