/* * Copyright (C) 2001-2003 by egnite Software GmbH. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * * 1. Redistributions of source code must retain the above copyright * notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright * notice, this list of conditions and the following disclaimer in the * documentation and/or other materials provided with the distribution. * 3. Neither the name of the copyright holders nor the names of * contributors may be used to endorse or promote products derived * from this software without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS * OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF * THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. * * For additional information see http://www.ethernut.de/ * * Portions of the following functions are derived from material which is * Copyright (c) 1985 by Microsoft Corporation. All rights are reserved. */ /* * $Log$ * Revision 1.3 2008/08/11 06:59:41 haraldkipp * BSD types replaced by stdint types (feature request #1282721). * * Revision 1.2 2003/12/19 22:26:38 drsung * Dox written. * * Revision 1.1 2003/11/24 18:07:37 drsung * first release * * */ #include #include #include "ctime.h" typedef struct { int yr; /* year of interest */ int yd; /* day of year */ long ms; /* milli-seconds in the day */ } transitiondate; /* * DST start and end structs. */ static transitiondate dststart = { -1, 0, 0L }; static transitiondate dstend = { -1, 0, 0L }; int _daylight = 1; /* daylight saving default enabled */ long _dstbias = -1 * 60L * 60L; /* bias for daylight saving in seconds */ long _timezone = 5L * 60L * 60L; /* default time zone is EST = -05:00:00 */ /* * The macro below is valid for years between 1901 and 2099, which easily * includes all years representable by the current implementation of time_t. */ #define IS_LEAP_YEAR(year) ( (year & 3) == 0 ) #define DAY_MILLISEC (24L * 60L * 60L * 1000L) static void cvtdate(int trantype, int datetype, int year, int month, int week, int dayofweek, int date, int hour, int min, int sec, int msec) { int yearday; int monthdow; if (datetype == 1) { /* * Transition day specified in day-in-month format. */ /* * Figure the year-day of the start of the month. */ yearday = 1 + (IS_LEAP_YEAR(year) ? _lpdays[month - 1] : _days[month - 1]); /* * Figure the day of the week of the start of the month. */ monthdow = (yearday + ((year - 70) * 365) + ((year - 1) >> 2) - _LEAP_YEAR_ADJUST + _BASE_DOW) % 7; /* * Figure the year-day of the transition date */ if (monthdow <= dayofweek) yearday += (dayofweek - monthdow) + (week - 1) * 7; else yearday += (dayofweek - monthdow) + week * 7; /* * May have to adjust the calculation above if week == 5 (meaning * the last instance of the day in the month). Check if year falls * beyond after month and adjust accordingly. */ if ((week == 5) && (yearday > (IS_LEAP_YEAR(year) ? _lpdays[month] : _days[month]))) { yearday -= 7; } } else { /* * Transition day specified as an absolute day */ yearday = IS_LEAP_YEAR(year) ? _lpdays[month - 1] : _days[month - 1]; yearday += date; } if (trantype == 1) { /* * Converted date was for the start of DST */ dststart.yd = yearday; dststart.ms = (long) msec + (1000L * (sec + 60L * (min + 60L * hour))); /* * Set year field of dststart so that unnecessary calls to * cvtdate() may be avoided. */ dststart.yr = year; } else { /* * Converted date was for the end of DST */ dstend.yd = yearday; dstend.ms = (long) msec + (1000L * (sec + 60L * (min + 60L * hour))); /* * The converted date is still a DST date. Must convert to a * standard (local) date while being careful the millisecond field * does not overflow or underflow. */ if ((dstend.ms += (_dstbias * 1000L)) < 0) { dstend.ms += DAY_MILLISEC; dstend.yd--; } else if (dstend.ms >= DAY_MILLISEC) { dstend.ms -= DAY_MILLISEC; dstend.yd++; } /* * Set year field of dstend so that unnecessary calls to cvtdate() * may be avoided. */ dstend.yr = year; } return; } int _isindst(tm * tb) { long ms; if (_daylight == 0) return 0; /* * Compute (recompute) the transition dates for daylight saving time * if necessary.The yr (year) fields of dststart and dstend is * compared to the year of interest to determine necessity. */ if ((tb->tm_year != dststart.yr) || (tb->tm_year != dstend.yr)) { cvtdate(1, 1, tb->tm_year, 3, /* March */ 5, /* last... */ 0, /* ...Sunday */ 0, 2, /* 02:00 (2 AM) */ 0, 0, 0); cvtdate(0, 1, tb->tm_year, 10, /* October */ 5, /* last... */ 0, /* ...Sunday */ 0, 2, /* 02:00 (2 AM) */ 0, 0, 0); } /* * Handle simple cases first. */ if (dststart.yd < dstend.yd) { /* * Northern hemisphere ordering */ if ((tb->tm_yday < dststart.yd) || (tb->tm_yday > dstend.yd)) return 0; if ((tb->tm_yday > dststart.yd) && (tb->tm_yday < dstend.yd)) return 1; } else { /* * Southern hemisphere ordering */ if ((tb->tm_yday < dstend.yd) || (tb->tm_yday > dststart.yd)) return 1; if ((tb->tm_yday > dstend.yd) && (tb->tm_yday < dststart.yd)) return 0; } ms = 1000L * (tb->tm_sec + 60L * tb->tm_min + 3600L * tb->tm_hour); if (tb->tm_yday == dststart.yd) { if (ms >= dststart.ms) return 1; else return 0; } else { if (ms < dstend.ms) return 1; else return 0; } }