Line data Source code
1 : /*
2 : Zipios -- a small C++ library that provides easy access to .zip files.
3 :
4 : Copyright (C) 2019 Made to Order Software Corporation
5 :
6 : This library is free software; you can redistribute it and/or
7 : modify it under the terms of the GNU Lesser General Public
8 : License as published by the Free Software Foundation; either
9 : version 2.1 of the License, or (at your option) any later version.
10 :
11 : This library is distributed in the hope that it will be useful,
12 : but WITHOUT ANY WARRANTY; without even the implied warranty of
13 : MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 : Lesser General Public License for more details.
15 :
16 : You should have received a copy of the GNU Lesser General Public
17 : License along with this library; if not, write to the Free Software
18 : Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
19 : */
20 :
21 : /** \file
22 : * \brief Implementation of the zipios::DOSDateTime class.
23 : *
24 : * This file is the implementation of the zipios::DOSDateTime class
25 : * which converts dates between Unix timestamps and DOS Date Time
26 : * timestamps.
27 : *
28 : * Keep in mind that the dates in a zip file use your local time,
29 : * whatever that is at the time you create the file. The get/set Unix
30 : * timestamp functions adjust the date to UTC as required.
31 : *
32 : * \sa https://docs.microsoft.com/en-us/windows/desktop/api/winbase/nf-winbase-dosdatetimetofiletime
33 : */
34 :
35 : #include "zipios/dosdatetime.hpp"
36 :
37 : #include "zipios/zipiosexceptions.hpp"
38 :
39 :
40 : namespace zipios
41 : {
42 :
43 :
44 : DOSDateTime::dosdatetime_t const DOSDateTime::g_min_dosdatetime; // Jan 1, 1980 00:00:00
45 : DOSDateTime::dosdatetime_t const DOSDateTime::g_max_dosdatetime; // Dec 31, 2107 23:59:59
46 :
47 :
48 :
49 :
50 : /** \brief Union used to convert the uint32_t to fields and vice versa.
51 : *
52 : * This union is used by the functions below to convert the basic
53 : * uint32_t dosdatetime_t values in a list of 6 fields.
54 : *
55 : * \todo
56 : * The fields are endian specific, we need to find the correct #ifdef
57 : * and swap the fields so it works on bigendian machines
58 : */
59 : union dosdatetime_convert_t
60 : {
61 : DOSDateTime::dosdatetime_t m_dosdatetime;
62 : struct fields
63 : {
64 : DOSDateTime::dosdatetime_t m_second : 5; // WARNING: the precision is every 2 seconds (0, 2, 4, etc.)
65 : DOSDateTime::dosdatetime_t m_minute : 6;
66 : DOSDateTime::dosdatetime_t m_hour : 5;
67 : DOSDateTime::dosdatetime_t m_mday : 5; // 1 to 31
68 : DOSDateTime::dosdatetime_t m_month : 4; // 1 to 12
69 : DOSDateTime::dosdatetime_t m_year : 7; // add 1980
70 : } m_fields;
71 : };
72 :
73 :
74 :
75 : namespace
76 : {
77 :
78 : /** \brief Number of days in a month.
79 : *
80 : * This table is used in the daysInMonth() function to determine the number
81 : * of days in the month. It is ignored if the month is February.
82 : */
83 : int const g_days_in_month[12] = {
84 : /* Jan */ 31,
85 : /* Feb */ 0, // special handling
86 : /* Mar */ 31,
87 : /* Apr */ 30,
88 : /* May */ 31,
89 : /* Jun */ 30,
90 : /* Jul */ 31,
91 : /* Aug */ 31,
92 : /* Sep */ 30,
93 : /* Oct */ 31,
94 : /* Nov */ 30,
95 : /* Dec */ 31
96 : };
97 :
98 :
99 : int const g_ydays[12] = {
100 : /* Jan */ 0,
101 : /* Feb */ 31,
102 : /* Mar */ 31 + 0, // special handling
103 : /* Apr */ 31 + 0 + 31,
104 : /* May */ 31 + 0 + 31 + 30,
105 : /* Jun */ 31 + 0 + 31 + 30 + 31,
106 : /* Jul */ 31 + 0 + 31 + 30 + 31 + 30,
107 : /* Aug */ 31 + 0 + 31 + 30 + 31 + 30 + 31,
108 : /* Sep */ 31 + 0 + 31 + 30 + 31 + 30 + 31 + 31,
109 : /* Oct */ 31 + 0 + 31 + 30 + 31 + 30 + 31 + 31 + 30,
110 : /* Nov */ 31 + 0 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31,
111 : /* Dec */ 31 + 0 + 31 + 30 + 31 + 30 + 31 + 31 + 30 + 31 + 30
112 : };
113 :
114 :
115 : }
116 :
117 :
118 :
119 : /** \brief Check whether this DOS Date & Date is valid.
120 : *
121 : * This function verifies to see whether the DOS Date & Time it holds is
122 : * valid. By default, the value is set to zero which represents an invalid
123 : * date (_not set_).
124 : *
125 : * \note
126 : * Remember that Zip file Date & Time are saved in an old MS-DOS format
127 : * which did not respect UTC. It instead represents local time. This
128 : * function returns true when the local time is valid, since the same
129 : * time will be shared around the globe, it will alway sbe considered
130 : * valid, but the Unix timestamp can look like a mismatch (the minimum
131 : * and maximum possible time stamps represented in a Unix time_t variable
132 : * will vary depending on your timezone settings.)
133 : *
134 : * \return true if the date is considered valid (represents an actual date
135 : * and time).
136 : *
137 : * \sa daysInMonth()
138 : */
139 668293 : bool DOSDateTime::isValid() const
140 : {
141 : dosdatetime_convert_t conv;
142 668293 : conv.m_dosdatetime = m_dosdatetime;
143 668293 : return conv.m_fields.m_second < 30 // remember we only keep `sec / 2` in a DOS time field
144 668293 : && conv.m_fields.m_minute < 60
145 668293 : && conv.m_fields.m_hour < 24
146 668293 : && conv.m_fields.m_mday > 0
147 668149 : && conv.m_fields.m_mday <= daysInMonth()
148 668149 : && conv.m_fields.m_month > 0
149 1336442 : && conv.m_fields.m_month < 13;
150 : }
151 :
152 :
153 : /** \brief Calculate the number of days in this date's month.
154 : *
155 : * This function uses this object's current month to determine how
156 : * many days are expected in that month.
157 : *
158 : * If the month field is invalid (not a number between 1 and 12 inclusive)
159 : * then the function returns -1 to indicate an error.
160 : *
161 : * The number of days is always 30 or 31 except for the month of February
162 : * in which case the function may return 28 or 29. For this reason, your
163 : * date must have the month and year you want to use to get a valid result
164 : * when calling this function.
165 : *
166 : * \note
167 : * This function is used to verify that the date month day is valid.
168 : *
169 : * \return The number of days in this date's current month.
170 : *
171 : * \sa isValid()
172 : */
173 668150 : int DOSDateTime::daysInMonth() const
174 : {
175 : dosdatetime_convert_t conv;
176 668150 : conv.m_dosdatetime = m_dosdatetime;
177 :
178 668150 : if(conv.m_fields.m_month == 0
179 668149 : || conv.m_fields.m_month > 12)
180 : {
181 1 : return -1;
182 : }
183 :
184 668149 : if(conv.m_fields.m_month == 2)
185 : {
186 : // Feb. depends on the year
187 : //
188 19038 : int year = conv.m_fields.m_year + 1980;
189 :
190 19038 : return ((year) % 400) == 0
191 : ? 29
192 18877 : : (((year) % 100) == 0
193 : ? 28
194 18727 : : (((year) % 4) == 0
195 : ? 29
196 56642 : : 28));
197 : }
198 :
199 649111 : return g_days_in_month[conv.m_fields.m_month - 1];
200 : }
201 :
202 :
203 : /** \brief Get the second.
204 : *
205 : * This function returns the second this DOSDateTime object represents.
206 : *
207 : * The second is between 0 and 59 inclusive.
208 : *
209 : * \note
210 : * The DOSDateTime format only supports 5 bits for seconds. In other words,
211 : * the number can't go all the way from 0 to 59. Instead, the second
212 : * is saved without bit 0. In other words, only an even number of second
213 : * is saved. In other words, 0, 2, 4, 6, up to 58.
214 : *
215 : * \return The second this DOS Date & Time represents.
216 : */
217 142 : int DOSDateTime::getSecond() const
218 : {
219 : dosdatetime_convert_t conv;
220 142 : conv.m_dosdatetime = m_dosdatetime;
221 142 : return conv.m_fields.m_second * 2;
222 : }
223 :
224 :
225 : /** \brief Get the minute.
226 : *
227 : * This function returns the minute this DOSDateTime object represents.
228 : *
229 : * The minute is between 0 and 59 inclusive.
230 : *
231 : * \return The minute this DOS Date & Time represents.
232 : */
233 142 : int DOSDateTime::getMinute() const
234 : {
235 : dosdatetime_convert_t conv;
236 142 : conv.m_dosdatetime = m_dosdatetime;
237 142 : return conv.m_fields.m_minute;
238 : }
239 :
240 :
241 : /** \brief Get the hour.
242 : *
243 : * This function returns the hour this DOSDateTime object represents.
244 : *
245 : * The hour is between 0 and 23 inclusive.
246 : *
247 : * \return The hour this DOS Date & Time represents.
248 : */
249 106 : int DOSDateTime::getHour() const
250 : {
251 : dosdatetime_convert_t conv;
252 106 : conv.m_dosdatetime = m_dosdatetime;
253 106 : return conv.m_fields.m_hour;
254 : }
255 :
256 :
257 : /** \brief Get the day of the month.
258 : *
259 : * This function returns the day of month this DOSDateTime object represents.
260 : *
261 : * The day is between 1 and 31. To know whether a day is valid, use the
262 : * daysInMonth() function which returns the maximum number of days for a
263 : * given month.
264 : *
265 : * \return The day of the month this DOS Date & Time represents.
266 : */
267 115 : int DOSDateTime::getMDay() const
268 : {
269 : dosdatetime_convert_t conv;
270 115 : conv.m_dosdatetime = m_dosdatetime;
271 115 : return conv.m_fields.m_mday;
272 : }
273 :
274 :
275 : /** \brief Get the month.
276 : *
277 : * This function returns the month this DOSDateTime object represents.
278 : *
279 : * The month is between 1 and 12.
280 : *
281 : * \return The month this DOS Date & Time represents.
282 : */
283 95 : int DOSDateTime::getMonth() const
284 : {
285 : dosdatetime_convert_t conv;
286 95 : conv.m_dosdatetime = m_dosdatetime;
287 95 : return conv.m_fields.m_month;
288 : }
289 :
290 :
291 : /** \brief Get the year.
292 : *
293 : * This function returns the year this DOSDateTime object represents.
294 : *
295 : * The year is limited between 1980 and 2107.
296 : *
297 : * \return The year this DOS Date & Time represents.
298 : */
299 2274 : int DOSDateTime::getYear() const
300 : {
301 : dosdatetime_convert_t conv;
302 2274 : conv.m_dosdatetime = m_dosdatetime;
303 2274 : return conv.m_fields.m_year + 1980;
304 : }
305 :
306 :
307 : /** \brief Set the second.
308 : *
309 : * This function can be used to only change the second of a DOSDateTime
310 : * object.
311 : *
312 : * \note
313 : * The DOSDateTime format only supports 5 bits for seconds. In other words,
314 : * the number can't go all the way from 0 to 59. Instead, the second
315 : * is saved without bit 0. In other words, only an even number of second
316 : * is saved. In other words, 0, 2, 4, 6, up to 58.
317 : *
318 : * \important
319 : * Leap seconds are not supported. Trying to pass 60 to this function
320 : * raises an InvalidException error.
321 : *
322 : * \exception InvalidException
323 : * The second is expected to be set to a number between 0 and 59 inclusive.
324 : * No exception is raised if an odd number is passed down. Bit 0 is simply
325 : * ignored.
326 : *
327 : * \param[in] second The new DOSDateTime number of seconds.
328 : */
329 144 : void DOSDateTime::setSecond(int second)
330 : {
331 144 : if(second < 0
332 124 : || second > 59)
333 : {
334 41 : throw InvalidException("Second is out of range for an MS-DOS Date & Time object. Range is [0, 59].");
335 : }
336 :
337 : dosdatetime_convert_t conv;
338 103 : conv.m_dosdatetime = m_dosdatetime;
339 103 : conv.m_fields.m_second = second / 2;
340 103 : m_dosdatetime = conv.m_dosdatetime;
341 103 : }
342 :
343 :
344 : /** \brief Set the minute.
345 : *
346 : * This function can be used to only change the minute of a DOSDateTime
347 : * object.
348 : *
349 : * \exception InvalidException
350 : * The minute is expected to be set to a number between 0 and 59 inclusive.
351 : *
352 : * \param[in] minute The new DOSDateTime number of minutes.
353 : */
354 144 : void DOSDateTime::setMinute(int minute)
355 : {
356 144 : if(minute < 0
357 124 : || minute > 59)
358 : {
359 41 : throw InvalidException("Minute is out of range for an MS-DOS Date & Time object. Range is [0, 59].");
360 : }
361 :
362 : dosdatetime_convert_t conv;
363 103 : conv.m_dosdatetime = m_dosdatetime;
364 103 : conv.m_fields.m_minute = minute;
365 103 : m_dosdatetime = conv.m_dosdatetime;
366 103 : }
367 :
368 :
369 : /** \brief Set the hour.
370 : *
371 : * This function can be used to only change the hour of a DOSDateTime
372 : * object.
373 : *
374 : * \exception InvalidException
375 : * The hour is expected to be set to a number between 0 and 23 inclusive.
376 : *
377 : * \param[in] hour The new DOSDateTime number of hours.
378 : */
379 108 : void DOSDateTime::setHour(int hour)
380 : {
381 108 : if(hour < 0
382 88 : || hour > 23)
383 : {
384 41 : throw InvalidException("Hour is out of range for an MS-DOS Date & Time object. Range is [0, 23].");
385 : }
386 :
387 : dosdatetime_convert_t conv;
388 67 : conv.m_dosdatetime = m_dosdatetime;
389 67 : conv.m_fields.m_hour = hour;
390 67 : m_dosdatetime = conv.m_dosdatetime;
391 67 : }
392 :
393 :
394 : /** \brief Set the day of the month.
395 : *
396 : * This function can be used to only change the day of the month of a
397 : * DOSDateTime object.
398 : *
399 : * \exception InvalidException
400 : * The day of the month is expected to be set to a number between 1 and 31
401 : * inclusive. An exception is raised if out of that range. Note that no
402 : * exception is raised if the day is invalid for a certain month because
403 : * at this point we can't be sure what the month will be. To verify once
404 : * you are done setting all the individual values, call isValid() to do
405 : * a final verification.
406 : *
407 : * \param[in] mday The new DOSDateTime day of the month.
408 : */
409 117 : void DOSDateTime::setMDay(int mday)
410 : {
411 117 : if(mday < 1
412 96 : || mday > 31)
413 : {
414 42 : throw InvalidException("Day of the month is out of range for an MS-DOS Date & Time object. Range is [1, 31].");
415 : }
416 :
417 : dosdatetime_convert_t conv;
418 75 : conv.m_dosdatetime = m_dosdatetime;
419 75 : conv.m_fields.m_mday = mday;
420 75 : m_dosdatetime = conv.m_dosdatetime;
421 75 : }
422 :
423 :
424 : /** \brief Set the month.
425 : *
426 : * This function can be used to only change the month of a DOSDateTime object.
427 : *
428 : * \exception InvalidException
429 : * The month is expected to be set to a number between 1 and 12 inclusive.
430 : *
431 : * \param[in] month The ne DOSDateTime month.
432 : */
433 97 : void DOSDateTime::setMonth(int month)
434 : {
435 97 : if(month < 1
436 76 : || month > 12)
437 : {
438 42 : throw InvalidException("Month out of range for an MS-DOS Date & Time object. Range is [1, 12].");
439 : }
440 :
441 : dosdatetime_convert_t conv;
442 55 : conv.m_dosdatetime = m_dosdatetime;
443 55 : conv.m_fields.m_month = month;
444 55 : m_dosdatetime = conv.m_dosdatetime;
445 55 : }
446 :
447 :
448 : /** \brief Set the year.
449 : *
450 : * This function can be used to only change the year this DOSDateTime object
451 : * represents.
452 : *
453 : * \exception InvalidException
454 : * The year is limited between 1980 and 2107. This exception is raised if the
455 : * year to out of this range.
456 : *
457 : * \return The year this DOS Date & Time represents.
458 : */
459 2276 : void DOSDateTime::setYear(int year)
460 : {
461 2276 : if(year < 1980
462 1296 : || year > 2107)
463 : {
464 1073 : throw InvalidException("Year out of range for an MS-DOS Date & Time object. Range is [1980, 2107].");
465 : }
466 :
467 : dosdatetime_convert_t conv;
468 1203 : conv.m_dosdatetime = m_dosdatetime;
469 1203 : conv.m_fields.m_year = year - 1980;
470 1203 : m_dosdatetime = conv.m_dosdatetime;
471 1203 : }
472 :
473 :
474 : /** \brief Retrieve the DOSDateTime value as is.
475 : *
476 : * This function returns the DOSDateTime value as is. It can then be used
477 : * in the zip file.
478 : *
479 : * \return The dosdatetime_t timestamp.
480 : */
481 1027824 : DOSDateTime::dosdatetime_t DOSDateTime::getDOSDateTime() const
482 : {
483 1027824 : return m_dosdatetime;
484 : }
485 :
486 :
487 : /** \brief Set the DOSDateTime value as is.
488 : *
489 : * This function sets this DOSDateTime object's timestamp to the specified
490 : * value. Any value is accepted by this function. To verify that the new
491 : * value is a valid date, use the isValid() function.
492 : *
493 : * \param[in] datetime The DOS Date & Time value.
494 : */
495 560902 : void DOSDateTime::setDOSDateTime(dosdatetime_t datetime)
496 : {
497 560902 : m_dosdatetime = datetime;
498 560902 : }
499 :
500 :
501 : /** \brief Set the DOSDateTime value from a Unix timestamp.
502 : *
503 : * This function accepts a Unix timestamp that gets converted to a
504 : * DOSDateTime object.
505 : *
506 : * A Unix timestamp is a time_t number representing seconds. 0 represents
507 : * the date Jan 1, 1970 at 00:00:00.
508 : *
509 : * The smallest Unix timestamp that can be represented in a DOSDateTime
510 : * object is 315532800 (0x12cea600) in UTC. Since the timestamp gets
511 : * converted to local time, though, the boundaries vary with the user's
512 : * timezone.
513 : *
514 : * The minimum date is represented as 0x00210000 in a DOSDateTime object.
515 : * This represents Jan 1, 1980 at 00:00:00, local time.
516 : *
517 : * The largest Unix timestamp that can be represented in a DOSDateTime
518 : * object is 4354819199 (0x10391447f) in UTC, since the timestamp gets
519 : * converted to local time, though, the boundaries vary with the user's
520 : * timezone.
521 : *
522 : * The maximum date is represented as 0xff9fbf7d in a DOSDateTime object.
523 : * Note that the Unix timestamp requires a 64 bit `time_t` representation
524 : * in order to reach the maximum DOSDateTime. With a 32 bit number,
525 : * the maximum is around 2037, about 70 years short. This maximum date
526 : * represents Dec 31, 2107 at 23:59:59, local time.
527 : *
528 : * \important
529 : * The DOSDateTime object only holds even seconds. Odd seconds are lost
530 : * at the time this function gets called.
531 : *
532 : * \exception InvalidException
533 : * In 64 bits, a Unix timestamp can represent very large dates in both
534 : * directions (in the past and future.) If the Unix timestamp represents a
535 : * local date and time before Jan 1, 1980 at 00:00:00 or after
536 : * Dec 31, 2107 at 23:59:58, then this function raises this exception.
537 : * It is likely to raise an exception on Dec 31, 2107 at 23:59:59 because
538 : * we round the time to the next even second.
539 : *
540 : * \param[in] unix_timestamp The time and stamp in Unix format.
541 : */
542 1047271 : void DOSDateTime::setUnixTimestamp(std::time_t unix_timestamp)
543 : {
544 : // round up to the next second
545 : //
546 1047271 : unix_timestamp += 1;
547 1047271 : unix_timestamp &= -2;
548 :
549 : struct tm t;
550 1047271 : localtime_r(&unix_timestamp, &t);
551 :
552 : //std::cerr << "test with: " << unix_timestamp << " -- " << t.tm_year
553 : // << " (" << (t.tm_year < 1980 - 1900 ? 1 : 0)
554 : // << ", " << (t.tm_year > 2107 - 1900 ? 1 : 0)
555 : // << ")\n";
556 :
557 1047271 : if(t.tm_year < 1980 - 1900
558 1027961 : || t.tm_year > 2107 - 1900)
559 : {
560 19767 : throw InvalidException("Year out of range for an MS-DOS Date & Time object. Range is [1980, 2107].");
561 : }
562 :
563 : dosdatetime_convert_t conv;
564 1027504 : conv.m_fields.m_second = t.tm_sec / 2; // already rounded up to the next second, so just divide by 2 is enough here
565 1027504 : conv.m_fields.m_minute = t.tm_min;
566 1027504 : conv.m_fields.m_hour = t.tm_hour;
567 1027504 : conv.m_fields.m_mday = t.tm_mday;
568 1027504 : conv.m_fields.m_month = t.tm_mon + 1;
569 1027504 : conv.m_fields.m_year = t.tm_year + 1900 - 1980;
570 :
571 1027504 : m_dosdatetime = conv.m_dosdatetime;
572 1027504 : }
573 :
574 :
575 : /** \brief Retrieve the DOSDateTime as a Unix timestamp.
576 : *
577 : * This function returns the DOSDateTime converted to a Unix timestamp.
578 : * On 64 bit platforms, all DOSDateTime can be converted to a Unix timestamp.
579 : * On a 32 bit platform, however, dates after 2037 can't be represented by
580 : * the Unix timestamp so this function throws (note that we did not check
581 : * the exact threshold because at this point I don't think it's too important.)
582 : *
583 : * \exception InvalidException
584 : * On 32 bit platform, dates that can't be represented in a Unix timestamp
585 : * throw this exception.
586 : *
587 : * \return The Unix timestamp representing the DOSDateTime object.
588 : *
589 : * \sa setUnixTimestamp()
590 : */
591 668085 : std::time_t DOSDateTime::getUnixTimestamp() const
592 : {
593 668085 : if(isValid())
594 : {
595 : dosdatetime_convert_t conv;
596 668065 : conv.m_dosdatetime = m_dosdatetime;
597 :
598 : struct tm t;
599 668065 : t.tm_sec = conv.m_fields.m_second * 2; // we lost the bottom bit, nothing we can do about it here
600 668065 : t.tm_min = conv.m_fields.m_minute;
601 668065 : t.tm_hour = conv.m_fields.m_hour;
602 668065 : t.tm_mday = conv.m_fields.m_mday;
603 668065 : t.tm_mon = conv.m_fields.m_month - 1;
604 668065 : t.tm_year = conv.m_fields.m_year + 1980 - 1900;
605 668065 : t.tm_wday = 0;
606 668065 : t.tm_yday = 0;
607 668065 : t.tm_isdst = -1;
608 :
609 : //std::cerr << "date to Unix timestamp: " << (t.tm_mon + 1) << " " << t.tm_mday << ", " << (t.tm_year + 1900)
610 : // << " " << t.tm_hour << ":" << t.tm_min << ":" << t.tm_sec << "\n";
611 :
612 : if(sizeof(std::time_t) == 4
613 : && t.tm_year >= 2038)
614 : {
615 : // the exact date is Jan 19, 2038 at 03:13:07 UTC
616 : // see https://en.wikipedia.org/wiki/Year_2038_problem
617 : //
618 : // we have no problem with 64 bits, max. year is about 292,000,000,000
619 : // although the tm_year is an int, so really we're limited to 2 billion
620 : // years, again just fine for a DOS Date is limited to 2107...
621 : //
622 : throw InvalidException("Year out of range for a 32 bit Unix Timestamp object. Range is (1901, 2038).");
623 : }
624 :
625 668065 : return mktime(&t);
626 :
627 : // // mktime() makes use of the timezone, here is some code that
628 : // // replaces mktime() with a UTC date conversion
629 : // //
630 : // time_t const year = t.tm_year + 1900;
631 : // time_t timestamp = (year - 1970LL) * 31536000LL
632 : // + ((year - 1969LL) / 4LL) * 86400LL
633 : // - ((year - 1901LL) / 100LL) * 86400LL
634 : // + ((year - 1601LL) / 400LL) * 86400LL
635 : // + (t.tm_mday + g_ydays[t.tm_mon] - 1) * 86400LL
636 : // + t.tm_hour * 3600LL
637 : // + t.tm_min * 60LL
638 : // + t.tm_sec * 1LL;
639 : // if(t.tm_mon >= 2)
640 : // {
641 : // // add seconds in February
642 : // //
643 : // timestamp += (year % 400 == 0
644 : // ? 29 // for year 2000
645 : // : (year % 100 == 0
646 : // ? 28 // for year 2100
647 : // : (year % 4 == 0
648 : // ? 29
649 : // : 28))) * 86400LL;
650 : // }
651 : //
652 : // return timestamp;
653 : }
654 :
655 20 : return 0;
656 : }
657 :
658 :
659 :
660 :
661 3 : } // zipios namespace
662 :
663 : // Local Variables:
664 : // mode: cpp
665 : // indent-tabs-mode: nil
666 : // c-basic-offset: 4
667 : // tab-width: 4
668 : // End:
669 :
670 : // vim: ts=4 sw=4 et
|