dostime.c
Go to the documentation of this file.
1/*
2 dostime.c - routines for converting UNIX time to MS-DOS time and vice versa.
3
4 Various Copyrights:
5
6 First written by Mark Adler, Richard B. Wales, Jean-loup Gailly,
7 Kai Uwe Rommel, Onno van der Linden and Igor Mandrichenko (1990-1997).
8 Tweaked further by Bryan Burns (1999).
9 Redesigned with full error checks by Alexis Wilke (2015).
10
11 This program is free software; you can redistribute it and/or
12 modify it under the terms of the GNU General Public License
13 as published by the Free Software Foundation; either version 2
14 of the License, or (at your option) any later version.
15
16 This program is distributed in the hope that it will be useful,
17 but WITHOUT ANY WARRANTY; without even the implied warranty of
18 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 GNU General Public License for more details.
20
21 You should have received a copy of the GNU General Public License
22 along with this program; if not, write to the Free Software
23 Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
24*/
25
57#include "dostime.h"
58
59#include <stdio.h>
60#include <stdlib.h>
61#include <string.h>
62
63
82{
83 // Jan 1, 1980 00:00:00 is the minimum
84 return 0x00210000;
85}
86
87
106{
107 // Dec 31, 2107 23:59:59 is the maximum
108 return 0xFF9FBF7D;
109}
110
111
132{
133 struct tm t; /* argument for mktime() */
134
135 memset(&t, 0, sizeof(t));
136
137 t.tm_isdst = -1; /* let mktime() determine if DST is in effect */
138 /* Convert DOS time to UNIX time_t format */
139 t.tm_sec = (((int)dostime << 1) & 0x3E);
140 t.tm_min = (((int)dostime >> 5) & 0x3F);
141 t.tm_hour = (((int)dostime >> 11) & 0x1F);
142 t.tm_mday = (((int)dostime >> 16) & 0x1F);
143 t.tm_mon = (((int)dostime >> 21) & 0x0F) - 1;
144 t.tm_year = (((int)dostime >> 25) & 0x7F) + 80;
145
146 if(t.tm_year < 80 || t.tm_year > 207
147 || t.tm_mon < 0 || t.tm_mon > 11
148 || t.tm_mday < 1 || t.tm_mday > 31
149 || t.tm_hour < 0 || t.tm_hour > 23
150 || t.tm_min < 0 || t.tm_min > 59
151 || t.tm_sec < 0 || t.tm_sec > 59)
152 {
153 return -1;
154 }
155
156 // A full round trip between Unix date to DOS and back to Unix works
157 // as is (without worry about the current timezone) because the DOS
158 // format makes use of localdate() and that's 1 to 1 compatible with
159 // mktime() which expects a local date too.
160 return mktime(&t);
161}
162
163
164/* \brief Convert a broken up date to a DOS date.
165 *
166 * Convert the date y/n/d and time h:m:s to a four byte DOS date and
167 * time (date in high two bytes, time in low two bytes allowing magnitude
168 * comparison).
169 *
170 * The function returns zero if the month, day, hour, minute, second are
171 * out of range.
172 *
173 * \todo
174 * The dostime_t type is 32 bits, although if it were 64 bits we would
175 * never have an overflow with the maximum. However, the Zip archive
176 * format only supports 32 bits as far as I know.
177 *
178 * \param[in] year The year.
179 * \param[in] month The month.
180 * \param[in] day The day.
181 * \param[in] hour The hour.
182 * \param[in] minute The minute.
183 * \param[in] second The second.
184 *
185 * \return The date parameters transformed in a DOS time value or zero if the
186 * date is considered invalid.
187 */
188dostime_t dostime(int year, int month, int day, int hour, int minute, int second)
189{
190 if(year < 1980 || year > 2107
191 || month < 1 || month > 12
192 || day < 1 || day > 31
193 || hour < 0 || hour > 23
194 || minute < 0 || minute > 59
195 || second < 0 || second > 59)
196 {
197 return 0;
198 }
199
200 return (((dostime_t) year - 1980) << 25)
201 | (((dostime_t) month ) << 21)
202 | (((dostime_t) day ) << 16)
203 | (((dostime_t) hour ) << 11)
204 | (((dostime_t) minute ) << 5)
205 | (((dostime_t) second ) >> 1); // 1 every other second
206}
207
208
219dostime_t unix2dostime(time_t unix_time)
220{
221 time_t even_time;
222 struct tm *s; /* result of localtime() */
223
224 even_time = (unix_time + 1) & ~1; /* Round up to even seconds. */
225 s = localtime(&even_time); /* Use local time since MSDOS does. */
226 return dostime(s->tm_year + 1900, s->tm_mon + 1, s->tm_mday,
227 s->tm_hour, s->tm_min, s->tm_sec);
228}
229
230
231// Local Variables:
232// mode: cpp
233// indent-tabs-mode: nil
234// c-basic-offset: 4
235// tab-width: 4
236// End:
237
238// vim: ts=4 sw=4 et
dostime_t mindostime()
Return the minimum possible value.
Definition: dostime.c:81
time_t dos2unixtime(dostime_t dostime)
Convert a DOS time to a Unix time.
Definition: dostime.c:131
dostime_t maxdostime()
Return the maximum possible value .
Definition: dostime.c:105
dostime_t unix2dostime(time_t unix_time)
Convert a Unix date to a DOS date.
Definition: dostime.c:219
dostime_t dostime(int year, int month, int day, int hour, int minute, int second)
Definition: dostime.c:188
Definitions for the MS-DOS to Unix time conversions.
uint32_t dostime_t
Definition: dostime.h:50