Skip to content

Instantly share code, notes, and snippets.

@dreamer
Created March 25, 2020 22:51
Show Gist options
  • Save dreamer/52210ad4ff0d17624562b58a2fa6b0de to your computer and use it in GitHub Desktop.
Save dreamer/52210ad4ff0d17624562b58a2fa6b0de to your computer and use it in GitHub Desktop.
#include <cstdint>
#include <cstdio>
#include <ctime>
/*
MS-DOS date and MS-DOS time are data formats associated with MS-DOS.
They are used in some file formats from the MS-DOS era. Each is a
16-bit integer.
MS-DOS date represents a day in the range 1980 to 2099 (or maybe 2107,
but dates after 2099 aren't always correctly handled).
MS-DOS time represents a 2-second interval within some day. The time
is usually expected to be in "local time", and there is no indication
of the time zone. This makes it fairly useless in the internet age.
*/
struct dos_tm {
// The MS-DOS date. The date is a packed value with the following format:
// Bits Description
// 0-4 Day of the month (1–31)
// 5-8 Month (1 = January, 2 = February, and so on)
// 9-15 Year offset from 1980 (add 1980 to get actual year)
uint16_t date_bits;
// The MS-DOS time. The time is a packed value with the following format:
// Bits Description
// 0-4 Second divided by 2
// 5-10 Minute (0–59)
// 11-15 Hour (0–23 on a 24-hour clock)
uint16_t time_bits;
};
// copied from DOS_PackTime
static uint16_t pack_dos_time(uint16_t hour, uint16_t min, uint16_t sec)
{
return (hour & 0x1f) << 11 | (min & 0x3f) << 5 | ((sec / 2) & 0x1f);
}
// copied from DOS_PackDate
static uint16_t pack_dos_date(uint16_t year, uint16_t mon, uint16_t day)
{
return ((year - 1980) & 0x7f) << 9 | (mon & 0x3f) << 5 | (day & 0x1f);
}
// TODO
static dos_tm localtime_to_dos(const tm &in)
{
dos_tm out;
out.date_bits = pack_dos_date(in.tm_hour, in.tm_min, in.tm_sec);
out.time_bits = pack_dos_time(in.tm_year + 1900, in.tm_mon + 1, in.tm_mday);
return out;
}
static tm dos_to_localtime(const dos_tm &in)
{
tm out = {0};
out.tm_year = (in.date_bits >> 9) + 1980 - 1900;
out.tm_mon = ((in.date_bits >> 5) & 0x0f) - 1;
out.tm_mday = in.date_bits & 0x1f;
out.tm_sec = (in.time_bits & 0x1f) * 2;
out.tm_min = (in.time_bits >> 5) & 0x3f;
out.tm_hour = (in.time_bits >> 11) & 0x1f;
out.tm_isdst = -1;
return out;
}
static time_t dos_to_unix_localtime(const dos_tm &in)
{
tm local_time = dos_to_localtime(in);
return mktime(&local_time);
}
int main()
{
char time_desc[100] = {};
int years[] = {1980, 1990, 2010, 2020, 2099};
int months[] = {1, 6, 12};
uint16_t days[] = {1, 15, 30};
for (auto y : years) {
for (auto m : months) {
for (auto d : days) {
dos_tm dt = {0};
dt.date_bits = pack_dos_date(y, m, d);
dt.time_bits = pack_dos_time(13, 37, 42);
const tm lt = dos_to_localtime(dt);
strftime(time_desc, sizeof(time_desc), "%F %T", &lt);
printf("%10s | %d-%d-%d \n",
time_desc, y, m, d);
}
}
}
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment