我试图理解如何将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
答案 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的时区偏移。
参考文献: