Decode date/time hexadecimal values found embedded within binary files

c#, decoding

Solution

You'll first want a utility method that reads bytes from a stream and handles the endian-ness. That could look like:

    public static byte[] ReadBytes(Stream s, int size, bool littleEndian) {
        var bytes = new byte[size];
        var len = s.Read(bytes, 0, size);
        if (len != size) throw new InvalidOperationException("Unexpected end of file");
        if (BitConverter.IsLittleEndian != littleEndian) Array.Reverse(bytes);
        return bytes;
    }

Windows dates are easy, supported by DateTime.FromFileTimeUtc() directly:

    public static DateTime ConvertWindowsDate(byte[] bytes) {
        if (bytes.Length != 8) throw new ArgumentException();
        return DateTime.FromFileTimeUtc(BitConverter.ToInt64(bytes, 0));
    }

Testing it with your value:

    var date1 = DateReaders.ConvertWindowsDate(DateReaders.ReadBytes(
                    new MemoryStream(new byte[]{0xFF,0x03,0xD2,0x31,0x5F,0xE1,0xC7,0x01}), 8, true));

Produces {8/18/2007 6:15:37 AM} as expected.

OLE dates are easy, supported by DateTime.FromOADate() directly:

    public static DateTime ConvertOLEDate(byte[] bytes) {
        if (bytes.Length != 8) throw new ArgumentException();
        return DateTime.FromOADate(BitConverter.ToDouble(bytes, 0));
    }

Testing it with your value:

    var date2 = DateReaders.ConvertOLEDate(DateReaders.ReadBytes(
                    new MemoryStream(new byte[] {0xFB,0xE8,0xDF,0x97,0x5D,0x3F,0xE3,0x40 }), 8, true));

Produces {12/2/2007 10:11:41 PM}

Unix date values are milliseconds from Jan 1st, 1970, 0:00 AM UTC:

    public static DateTime ConvertUnixDate(byte[] bytes) {
        if (bytes.Length != 4) throw new ArgumentException();
        return new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(
                  BitConverter.ToUInt32(bytes, 0));
    }

Testing it with your value:

    var date3 = DateReaders.ConvertUnixDate(DateReaders.ReadBytes(
                   new MemoryStream(new byte[] {0x46,0xC3,0xB4,0x00}), 4, false));

Produces {8/16/2007 2:18:40 AM}

Apple Mac absolute time is documented to be CPU dependent and requires conversion on the machine that generated it. The shown value "219216022" is quirky, it appears to decimal instead of hex like all the other ones. I'll follow Baldrick's lead with:

public static DateTime ConvertAppleDate(byte[] bytes) {
    if (bytes.Length != 4) throw new ArgumentException();
    return new DateTime(2001, 1, 1, 0, 0, 0, DateTimeKind.Utc).AddSeconds(
              BitConverter.ToUInt32(bytes, 0));
}

HFS dates are seconds since Jan 1st, 1904, 0:00 AM. Do note that HFS dates are local time but HFS Plus dates are UTC. I'll assume local since that's the result you documented:

    public static DateTime ConvertHFSDate(byte[] bytes) {
        if (bytes.Length != 4) throw new ArgumentException();
        return new DateTime(1904, 1, 1, 0, 0, 0, DateTimeKind.Local).AddSeconds(
                  BitConverter.ToUInt32(bytes, 0));
    }

Testing it with your value:

    var date5 = DateReaders.ConvertHFSDate(DateReaders.ReadBytes(
                   new MemoryStream(new byte[] {0xCD,0x4E,0x55,0xC3 }), 4, true));

Produces {11/5/2007 10:50:53 PM}

Problem

I am trying to write a C# program similar to the one on this website: http://www.digital-detective.co.uk/freetools/decode.asp Can you please tell me how I can convert the hex numbers listed in the following bulletins to Date/Time values. - Windows 64 bit (little endian) hex value `FF03D2315FE1C701` should converts to = `Sat, 18 August 2007 06:15:37 UTC` - Windows 64 bit OLE hex value `FBE8DF975D3FE340` should converts to = `Sun, 02 December 2007 22:11:42 UTC` - Unix 32 bit (big endian) hex value `46C3B400` should converts to = `Thu, 16 August 2007 02:18:40 UTC` - Apple Mac Absolute hex value `219216022` should converts to = `Thu, 13 December 2007 05:20:22 UTC` - HFS 32 bit (little endian) hex value `CD4E55C3` should converts to = `Mon, 05 November 2007 22:50:53 Local` I was trying to use the following code to do that, but it doesn't return the correct result: ``` double decValue = int.Parse("A2C3B446", System.Globalization.NumberStyles.HexNumber); System.DateTime dtDateTime = new DateTime(2013, 1, 1, 0, 0, 0, 0); dtDateTime = dtDateTime.AddSeconds(decValue).ToLocalTime(); Console.WriteLine("Decimal Value: " + decValue); Console.WriteLine(dtDateTime); ```

Original source