time.c (03.02.12)
exFAT file system implementation library.
- Copyright (C) 2010-2013 Andrew Nayenko
+ Free exFAT implementation.
+ Copyright (C) 2010-2023 Andrew Nayenko
- This program is free software: you can redistribute it and/or modify
+ This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
- the Free Software Foundation, either version 3 of the License, or
+ the Free Software Foundation, either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
- You should have received a copy of the GNU General Public License
- along with this program. If not, see <http://www.gnu.org/licenses/>.
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation, Inc.,
+ 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*/
#include "exfat.h"
0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334
};
-time_t exfat_exfat2unix(le16_t date, le16_t time, uint8_t centisec)
+time_t exfat_exfat2unix(le16_t date, le16_t time, uint8_t centisec,
+ uint8_t tzoffset)
{
time_t unix_time = EPOCH_DIFF_SEC;
uint16_t ndate = le16_to_cpu(date);
unix_time += centisec / 100;
/* exFAT stores timestamps in local time, so we correct it to UTC */
- unix_time += exfat_timezone;
+ if (tzoffset & 0x80)
+ /* lower 7 bits are signed timezone offset in 15 minute increments */
+ unix_time -= (int8_t)(tzoffset << 1) * 15 * 60 / 2;
+ else
+ /* timezone offset not present, assume our local timezone */
+ unix_time += exfat_timezone;
return unix_time;
}
void exfat_unix2exfat(time_t unix_time, le16_t* date, le16_t* time,
- uint8_t* centisec)
+ uint8_t* centisec, uint8_t* tzoffset)
{
time_t shift = EPOCH_DIFF_SEC + exfat_timezone;
uint16_t day, month, year;
*time = cpu_to_le16(twosec | (min << 5) | (hour << 11));
if (centisec)
*centisec = (unix_time % 2) * 100;
+
+ /* record our local timezone offset in exFAT (15 minute increment) format */
+ *tzoffset = (uint8_t)(-exfat_timezone / 60 / 15) | 0x80;
}
void exfat_tzset(void)
{
time_t now;
+ struct tm* utc;
tzset();
now = time(NULL);
- exfat_timezone = mktime(gmtime(&now)) - now;
+ utc = gmtime(&now);
+ /* gmtime() always sets tm_isdst to 0 because daylight savings never
+ affect UTC. Setting tm_isdst to -1 makes mktime() to determine whether
+ summer time is in effect. */
+ utc->tm_isdst = -1;
+ exfat_timezone = mktime(utc) - now;
}