Search code examples
cdatetimetimetimestampfat32

Unix timestamp to FAT timestamp


Im trying to convert a time structure to a FAT timestamp. My code looks like:

unsigned long Fat(tm_struct pTime)
{
    unsigned long FatTime = 0;

    FatTime |= (pTime.seconds / 2) >> 1;
    FatTime |= (pTime.minutes) << 5;
    FatTime |= (pTime.hours) << 11;
    FatTime |= (pTime.days) << 16;
    FatTime |= (pTime.months) << 21;
    FatTime |= (pTime.years + 20) << 25;

    return FatTime;
}

Does someone have the correct code?


Solution

  • The DOS date/time format is a bitmask:
    
                   24                16                 8                 0
    +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
    |Y|Y|Y|Y|Y|Y|Y|M| |M|M|M|D|D|D|D|D| |h|h|h|h|h|m|m|m| |m|m|m|s|s|s|s|s|
    +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+ +-+-+-+-+-+-+-+-+
     \___________/\________/\_________/ \________/\____________/\_________/
        year        month       day      hour       minute        second
    
    The year is stored as an offset from 1980. 
    Seconds are stored in two-second increments. 
    (So if the "second" value is 15, it actually represents 30 seconds.)
    

    I dont know the tm_struct you are using but if it's http://www.cplusplus.com/reference/ctime/tm/ then

    unsigned long FatTime = ((pTime.tm_year - 80) << 25) | 
                            ((pTime.tm_mon + 1) << 21) |
                            (pTime.tm_mday << 16) |
                            (pTime.tm_hour << 11) |
                            (pTime.tm_min << 5) |
                            (pTime.tm_sec >> 1);
    

    Edit: I added the +1 in month as mentioned in the comments