如何使用C#将2字节C日期转换为.NET DateTime?

时间:2017-02-01 03:16:45

标签: c# c date datetime

我无法读取/写入包含日期信息的二进制文件。覆盖文件相关部分的结构是:

typedef struct {
    short int  blah1;       
    short int  blah2;        
    short int  blah3;        
    short int  blah4;  
    short int  blah5;   
    WORD       date_created;   /* Creation date, packed as in a directory */
    time_t     time;           /* Creation time, from bios interrupt 1Ah */
    etc

由此我相信2字节(WORD)用于存储日期,4字节用于存储time_t。

我有一个样本文件,其中应包含日期01/08/2001(dd / mm / yyyy)。我从文件的 date_created 部分读取的2字节值是十进制0x0D​​和0x2B。

如果我提取了错误的值,文件的前80个字节为here并转储如下

od -t x1 "20010801 Fragment.bin"     
0000000 01 00 1c 01 00 00 bc 02 00 00 0d 2b 8b 00 77 3b
0000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
*
0000120

我已经四处寻找,但找不到任何与日期存档有关的信息。也许我错误地解释了问题,因此在我看到它们时没有正确搜索或没有识别出答案 - 抱歉 - 不是C程序员。

非常感谢能够提供帮助的任何人。

re:time_t,我想我正在使用:

正确转换它
public static UInt32 To_time_t(DateTime toConvert)
{
    return (UInt32)(toConvert - new DateTime(1970, 1, 1)).TotalSeconds;
}

public static DateTime From_time_t(UInt32 toConvert)
{
    DateTime epoch = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
    return epoch.AddSeconds(toConvert);
}

...但如果这是错误的做法,请告诉我。

1 个答案:

答案 0 :(得分:0)

非常感谢回复!根据Raymond Chen的链接,我已经将下面的代码作为起点。它返回的日期为13/08/2001,非常接近预期日期。感谢Oliver,我找到了与遗留应用程序的联系,他们确认日期为13/08/2001(与根据收集日期命名文件的假设相矛盾。)

再次感谢。

如果它帮助其他人,我的代码和单元测试是:

    internal struct Systime
    {
        internal UInt16 Year;
        internal UInt16 Month;
        internal UInt16 DayOfWeek;
        internal UInt16 Day;
        internal UInt16 Hour;
        internal UInt16 Minute;
        internal UInt16 Second;
        internal UInt16 Milliseconds;
    }

    internal struct FileTime
    {
        internal UInt32 dwLowDateTime;
        internal UInt32 dwHighDateTime;
    }

[DllImport("Kernel32.dll", CharSet = CharSet.Ansi)]
private static extern bool DosDateTimeToFileTime(UInt16 wFatDate, UInt16 wFatTime, ref FileTime lpFileTime);

[DllImport("Kernel32.dll", CharSet = CharSet.Ansi)]
private static extern bool FileTimeToSystemTime(ref FileTime lpFileTime, ref Systime lpSystemTime);

[DllImport("Kernel32.dll", CharSet = CharSet.Ansi)]
private static extern bool FileTimeToDosDateTime(ref FileTime lpFileTime, ref UInt16 wFatDate, ref UInt16 wFatTime);

[DllImport("Kernel32.dll", CharSet = CharSet.Ansi)]
private static extern bool SystemTimeToFileTime(ref Systime lpSystemTime, ref FileTime lpFileTime);


public static DateTime FromMSDosDate(UInt16 toConvert)
{
    FileTime fileTime = new FileTime();
    Systime systemTime = new Systime();

    DosDateTimeToFileTime(toConvert, 0, ref fileTime);
    FileTimeToSystemTime(ref fileTime, ref systemTime);

    return new DateTime(systemTime.Year, systemTime.Month, systemTime.Day, 0, 0, 0);
}

public static UInt16 ToMSDosDate(DateTime toConvert)
{
    Systime systemTime = new Systime();
    FileTime fileTime = new FileTime();
    UInt16 fatDate = 0;
    UInt16 fatTime = 0;

    systemTime.Day = (UInt16)toConvert.Day;
    systemTime.Month = (UInt16)toConvert.Month;
    systemTime.Year = (UInt16)toConvert.Year;

    SystemTimeToFileTime(ref systemTime, ref fileTime);
    FileTimeToDosDateTime(ref fileTime, ref fatDate, ref fatTime);

    return fatDate;
}

[TestMethod]
public void Test_MSDos_Date()
{
    UInt16 testDate = 11021; // int value read from binary test file...
    DateTime expected = new DateTime(2001, 8, 13, 0, 0, 0);
    Assert.AreEqual(expected, Utils.FromMSDosDate(testDate));
    Assert.AreEqual(testDate, Utils.ToMSDosDate(expected));
}