Important changes to repositories hosted on mbed.com
Mbed hosted mercurial repositories are deprecated and are due to be permanently deleted in July 2026.
To keep a copy of this software download the repository Zip archive or clone locally using Mercurial.
It is also possible to export all your personal repositories from the account settings page.
Dependents: oldheating gps motorhome heating
time.c@26:0421132e6eaf, 2018-01-25 (annotated)
- Committer:
- andrewboyson
- Date:
- Thu Jan 25 07:54:54 2018 +0000
- Revision:
- 26:0421132e6eaf
Changed ticks from a count of ns to a fixed fraction of 30bits. This makes it much easier to convert to and from NTP and time_t
Who changed what in which revision?
User | Revision | Line number | New contents of line |
---|---|---|---|
andrewboyson | 26:0421132e6eaf | 1 | #include <stdlib.h> |
andrewboyson | 26:0421132e6eaf | 2 | #include <time.h> |
andrewboyson | 26:0421132e6eaf | 3 | #include <stdio.h> |
andrewboyson | 26:0421132e6eaf | 4 | #include <string.h> |
andrewboyson | 26:0421132e6eaf | 5 | #include <stdbool.h> |
andrewboyson | 26:0421132e6eaf | 6 | |
andrewboyson | 26:0421132e6eaf | 7 | #define STD_OFFSET 0 |
andrewboyson | 26:0421132e6eaf | 8 | #define DST_OFFSET 1 |
andrewboyson | 26:0421132e6eaf | 9 | |
andrewboyson | 26:0421132e6eaf | 10 | static bool isLeapYear(int year) |
andrewboyson | 26:0421132e6eaf | 11 | { |
andrewboyson | 26:0421132e6eaf | 12 | year += 1900; |
andrewboyson | 26:0421132e6eaf | 13 | bool leapYear = !(year & 0x3); |
andrewboyson | 26:0421132e6eaf | 14 | if (year >= 2100) |
andrewboyson | 26:0421132e6eaf | 15 | { |
andrewboyson | 26:0421132e6eaf | 16 | if (year % 100 == 0) leapYear = false; |
andrewboyson | 26:0421132e6eaf | 17 | if (year % 400 == 0) leapYear = true; |
andrewboyson | 26:0421132e6eaf | 18 | } |
andrewboyson | 26:0421132e6eaf | 19 | return leapYear; |
andrewboyson | 26:0421132e6eaf | 20 | |
andrewboyson | 26:0421132e6eaf | 21 | } |
andrewboyson | 26:0421132e6eaf | 22 | static int monthLength(int year, int month) |
andrewboyson | 26:0421132e6eaf | 23 | { |
andrewboyson | 26:0421132e6eaf | 24 | static char monthlengths[] = {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 }; |
andrewboyson | 26:0421132e6eaf | 25 | int daysInMonth = monthlengths[month]; |
andrewboyson | 26:0421132e6eaf | 26 | if (month == 1 && isLeapYear(year)) daysInMonth++; //February is month 1 of months 0 to 11 |
andrewboyson | 26:0421132e6eaf | 27 | return daysInMonth; |
andrewboyson | 26:0421132e6eaf | 28 | } |
andrewboyson | 26:0421132e6eaf | 29 | static bool isDst(int year, int month, int dayOfMonth, int dayOfWeek, int hours) |
andrewboyson | 26:0421132e6eaf | 30 | { |
andrewboyson | 26:0421132e6eaf | 31 | //Find the last Sunday in the month |
andrewboyson | 26:0421132e6eaf | 32 | int lastDayOfMonth = monthLength(year, month); |
andrewboyson | 26:0421132e6eaf | 33 | int daysToEndOfMonth = lastDayOfMonth - dayOfMonth; |
andrewboyson | 26:0421132e6eaf | 34 | int dayOfWeekOfLastDayOfMonth = (dayOfWeek + daysToEndOfMonth) % 7; |
andrewboyson | 26:0421132e6eaf | 35 | int lastSundayDayOfMonth = lastDayOfMonth - dayOfWeekOfLastDayOfMonth; |
andrewboyson | 26:0421132e6eaf | 36 | |
andrewboyson | 26:0421132e6eaf | 37 | //Check each month |
andrewboyson | 26:0421132e6eaf | 38 | if (month <= 1) return false; //Jan, Feb |
andrewboyson | 26:0421132e6eaf | 39 | if (month == 2) //Mar - DST true after 1am UTC on the last Sunday in March |
andrewboyson | 26:0421132e6eaf | 40 | { |
andrewboyson | 26:0421132e6eaf | 41 | if (dayOfMonth < lastSundayDayOfMonth) return false; |
andrewboyson | 26:0421132e6eaf | 42 | if (dayOfMonth == lastSundayDayOfMonth) return hours >= 1; |
andrewboyson | 26:0421132e6eaf | 43 | if (dayOfMonth > lastSundayDayOfMonth) return true; |
andrewboyson | 26:0421132e6eaf | 44 | } |
andrewboyson | 26:0421132e6eaf | 45 | if (month >= 3 && month <= 8) return true; //Apr, May, Jun, Jul, Aug, Sep |
andrewboyson | 26:0421132e6eaf | 46 | if (month == 9) //Oct - DST false after 1am UTC on the last Sunday in October |
andrewboyson | 26:0421132e6eaf | 47 | { |
andrewboyson | 26:0421132e6eaf | 48 | if (dayOfMonth < lastSundayDayOfMonth) return true; |
andrewboyson | 26:0421132e6eaf | 49 | if (dayOfMonth == lastSundayDayOfMonth) return hours < 1; |
andrewboyson | 26:0421132e6eaf | 50 | if (dayOfMonth > lastSundayDayOfMonth) return false; |
andrewboyson | 26:0421132e6eaf | 51 | } |
andrewboyson | 26:0421132e6eaf | 52 | if (month >= 10) return false; //Nov, Dec |
andrewboyson | 26:0421132e6eaf | 53 | return false; |
andrewboyson | 26:0421132e6eaf | 54 | } |
andrewboyson | 26:0421132e6eaf | 55 | static void calculateDayOfYearAndWeek(int thisYear, int thisMonth, int thisMonthDay, int* pDayOfYear, int* pDayOfWeek) |
andrewboyson | 26:0421132e6eaf | 56 | { |
andrewboyson | 26:0421132e6eaf | 57 | int dayOfYear = 0; //1 Jan is day 0 |
andrewboyson | 26:0421132e6eaf | 58 | int dayOfWeek = 4; //1 Jan 1970 is a Thursday |
andrewboyson | 26:0421132e6eaf | 59 | |
andrewboyson | 26:0421132e6eaf | 60 | //Add days of each whole year |
andrewboyson | 26:0421132e6eaf | 61 | for (int y = 70; y < thisYear; y++) |
andrewboyson | 26:0421132e6eaf | 62 | { |
andrewboyson | 26:0421132e6eaf | 63 | int lengthOfYear = isLeapYear(y) ? 366 : 365; |
andrewboyson | 26:0421132e6eaf | 64 | dayOfWeek += lengthOfYear; |
andrewboyson | 26:0421132e6eaf | 65 | } |
andrewboyson | 26:0421132e6eaf | 66 | |
andrewboyson | 26:0421132e6eaf | 67 | //Add days of each whole month |
andrewboyson | 26:0421132e6eaf | 68 | for (int m = 0; m < thisMonth; m++) |
andrewboyson | 26:0421132e6eaf | 69 | { |
andrewboyson | 26:0421132e6eaf | 70 | int lengthOfMonth = monthLength(thisYear, m); |
andrewboyson | 26:0421132e6eaf | 71 | dayOfYear += lengthOfMonth; |
andrewboyson | 26:0421132e6eaf | 72 | dayOfWeek += lengthOfMonth; |
andrewboyson | 26:0421132e6eaf | 73 | } |
andrewboyson | 26:0421132e6eaf | 74 | |
andrewboyson | 26:0421132e6eaf | 75 | //Add days of part month |
andrewboyson | 26:0421132e6eaf | 76 | thisMonthDay--; //thisMonthDay is 01 to 31 where we need 00 to 30 |
andrewboyson | 26:0421132e6eaf | 77 | dayOfYear += thisMonthDay; |
andrewboyson | 26:0421132e6eaf | 78 | dayOfWeek += thisMonthDay; |
andrewboyson | 26:0421132e6eaf | 79 | |
andrewboyson | 26:0421132e6eaf | 80 | //Update the day of year and day of week parts of the struct tm |
andrewboyson | 26:0421132e6eaf | 81 | *pDayOfYear = dayOfYear; // 0 --> 365 |
andrewboyson | 26:0421132e6eaf | 82 | *pDayOfWeek = dayOfWeek % 7; // 0 --> 6 |
andrewboyson | 26:0421132e6eaf | 83 | } |
andrewboyson | 26:0421132e6eaf | 84 | void TimeIncrement(struct tm* ptm) |
andrewboyson | 26:0421132e6eaf | 85 | { |
andrewboyson | 26:0421132e6eaf | 86 | ptm->tm_sec++; |
andrewboyson | 26:0421132e6eaf | 87 | if (ptm->tm_sec > 59) |
andrewboyson | 26:0421132e6eaf | 88 | { |
andrewboyson | 26:0421132e6eaf | 89 | ptm->tm_sec = 0; |
andrewboyson | 26:0421132e6eaf | 90 | ptm->tm_min++; |
andrewboyson | 26:0421132e6eaf | 91 | } |
andrewboyson | 26:0421132e6eaf | 92 | if (ptm->tm_min > 59) |
andrewboyson | 26:0421132e6eaf | 93 | { |
andrewboyson | 26:0421132e6eaf | 94 | ptm->tm_min = 0; |
andrewboyson | 26:0421132e6eaf | 95 | ptm->tm_hour++; |
andrewboyson | 26:0421132e6eaf | 96 | } |
andrewboyson | 26:0421132e6eaf | 97 | if (ptm->tm_hour > 23) |
andrewboyson | 26:0421132e6eaf | 98 | { |
andrewboyson | 26:0421132e6eaf | 99 | ptm->tm_hour = 0; |
andrewboyson | 26:0421132e6eaf | 100 | ptm->tm_wday++; |
andrewboyson | 26:0421132e6eaf | 101 | if (ptm->tm_wday > 6) ptm->tm_wday = 0; |
andrewboyson | 26:0421132e6eaf | 102 | ptm->tm_yday++; |
andrewboyson | 26:0421132e6eaf | 103 | ptm->tm_mday++; |
andrewboyson | 26:0421132e6eaf | 104 | if (ptm->tm_mday > monthLength(ptm->tm_year, ptm->tm_mon)) |
andrewboyson | 26:0421132e6eaf | 105 | { |
andrewboyson | 26:0421132e6eaf | 106 | ptm->tm_mon++; |
andrewboyson | 26:0421132e6eaf | 107 | if (ptm->tm_mon > 11) |
andrewboyson | 26:0421132e6eaf | 108 | { |
andrewboyson | 26:0421132e6eaf | 109 | ptm->tm_year++; |
andrewboyson | 26:0421132e6eaf | 110 | ptm->tm_yday = 0; |
andrewboyson | 26:0421132e6eaf | 111 | ptm->tm_mon = 0; |
andrewboyson | 26:0421132e6eaf | 112 | } |
andrewboyson | 26:0421132e6eaf | 113 | ptm->tm_mday = 1; |
andrewboyson | 26:0421132e6eaf | 114 | } |
andrewboyson | 26:0421132e6eaf | 115 | } |
andrewboyson | 26:0421132e6eaf | 116 | } |
andrewboyson | 26:0421132e6eaf | 117 | static void normalise(int* pHours, int* pDayOfWeek, int* pDayOfMonth, int* pMonth, int * pDayOfYear, int* pYear) |
andrewboyson | 26:0421132e6eaf | 118 | { |
andrewboyson | 26:0421132e6eaf | 119 | if (*pHours > 23) |
andrewboyson | 26:0421132e6eaf | 120 | { |
andrewboyson | 26:0421132e6eaf | 121 | *pHours -= 24; |
andrewboyson | 26:0421132e6eaf | 122 | ++*pDayOfWeek; |
andrewboyson | 26:0421132e6eaf | 123 | if (*pDayOfWeek > 6) *pDayOfWeek = 0; |
andrewboyson | 26:0421132e6eaf | 124 | ++*pDayOfYear; |
andrewboyson | 26:0421132e6eaf | 125 | ++*pDayOfMonth; |
andrewboyson | 26:0421132e6eaf | 126 | if (*pDayOfMonth > monthLength(*pYear, *pMonth)) |
andrewboyson | 26:0421132e6eaf | 127 | { |
andrewboyson | 26:0421132e6eaf | 128 | ++*pMonth; |
andrewboyson | 26:0421132e6eaf | 129 | if (*pMonth > 11) |
andrewboyson | 26:0421132e6eaf | 130 | { |
andrewboyson | 26:0421132e6eaf | 131 | ++*pYear; |
andrewboyson | 26:0421132e6eaf | 132 | *pDayOfYear = 0; |
andrewboyson | 26:0421132e6eaf | 133 | *pMonth = 0; |
andrewboyson | 26:0421132e6eaf | 134 | } |
andrewboyson | 26:0421132e6eaf | 135 | *pDayOfMonth = 1; |
andrewboyson | 26:0421132e6eaf | 136 | } |
andrewboyson | 26:0421132e6eaf | 137 | } |
andrewboyson | 26:0421132e6eaf | 138 | |
andrewboyson | 26:0421132e6eaf | 139 | if (*pHours < 0) |
andrewboyson | 26:0421132e6eaf | 140 | { |
andrewboyson | 26:0421132e6eaf | 141 | *pHours += 24; |
andrewboyson | 26:0421132e6eaf | 142 | --*pDayOfWeek; |
andrewboyson | 26:0421132e6eaf | 143 | if (*pDayOfWeek < 0) *pDayOfWeek = 6; |
andrewboyson | 26:0421132e6eaf | 144 | --*pDayOfYear; |
andrewboyson | 26:0421132e6eaf | 145 | --*pDayOfMonth; |
andrewboyson | 26:0421132e6eaf | 146 | if (*pDayOfMonth < 1) |
andrewboyson | 26:0421132e6eaf | 147 | { |
andrewboyson | 26:0421132e6eaf | 148 | --*pMonth; |
andrewboyson | 26:0421132e6eaf | 149 | if (*pMonth < 0) |
andrewboyson | 26:0421132e6eaf | 150 | { |
andrewboyson | 26:0421132e6eaf | 151 | --*pYear; |
andrewboyson | 26:0421132e6eaf | 152 | *pDayOfYear = isLeapYear(*pYear) ? 365 : 364; |
andrewboyson | 26:0421132e6eaf | 153 | *pMonth = 11; |
andrewboyson | 26:0421132e6eaf | 154 | } |
andrewboyson | 26:0421132e6eaf | 155 | *pDayOfMonth = monthLength(*pYear, *pMonth); |
andrewboyson | 26:0421132e6eaf | 156 | } |
andrewboyson | 26:0421132e6eaf | 157 | } |
andrewboyson | 26:0421132e6eaf | 158 | } |
andrewboyson | 26:0421132e6eaf | 159 | static void addYears(int* pYear, int* pDayOfWeek, int* pDaysLeft) |
andrewboyson | 26:0421132e6eaf | 160 | { |
andrewboyson | 26:0421132e6eaf | 161 | while(1) |
andrewboyson | 26:0421132e6eaf | 162 | { |
andrewboyson | 26:0421132e6eaf | 163 | //See if it is a leap year |
andrewboyson | 26:0421132e6eaf | 164 | int leapYear = isLeapYear(*pYear); |
andrewboyson | 26:0421132e6eaf | 165 | |
andrewboyson | 26:0421132e6eaf | 166 | //Find the number of days in this year |
andrewboyson | 26:0421132e6eaf | 167 | int daysInYear = leapYear ? 366 : 365; |
andrewboyson | 26:0421132e6eaf | 168 | |
andrewboyson | 26:0421132e6eaf | 169 | //Stop if this is the final year |
andrewboyson | 26:0421132e6eaf | 170 | if (*pDaysLeft < daysInYear) break; |
andrewboyson | 26:0421132e6eaf | 171 | |
andrewboyson | 26:0421132e6eaf | 172 | //Calculate the current day of the week at the start of the year |
andrewboyson | 26:0421132e6eaf | 173 | *pDayOfWeek += leapYear ? 2 : 1; |
andrewboyson | 26:0421132e6eaf | 174 | if (*pDayOfWeek >= 7) *pDayOfWeek -= 7; |
andrewboyson | 26:0421132e6eaf | 175 | |
andrewboyson | 26:0421132e6eaf | 176 | //Move on to the next year |
andrewboyson | 26:0421132e6eaf | 177 | *pDaysLeft -= daysInYear; |
andrewboyson | 26:0421132e6eaf | 178 | ++*pYear; |
andrewboyson | 26:0421132e6eaf | 179 | } |
andrewboyson | 26:0421132e6eaf | 180 | } |
andrewboyson | 26:0421132e6eaf | 181 | static void addMonths(int year, int* pMonth, int* pDaysLeft) |
andrewboyson | 26:0421132e6eaf | 182 | { |
andrewboyson | 26:0421132e6eaf | 183 | while(1) |
andrewboyson | 26:0421132e6eaf | 184 | { |
andrewboyson | 26:0421132e6eaf | 185 | int daysInMonth = monthLength(year, *pMonth); |
andrewboyson | 26:0421132e6eaf | 186 | |
andrewboyson | 26:0421132e6eaf | 187 | //Stop if this is the last month |
andrewboyson | 26:0421132e6eaf | 188 | if (*pDaysLeft < daysInMonth) break; |
andrewboyson | 26:0421132e6eaf | 189 | |
andrewboyson | 26:0421132e6eaf | 190 | //Move onto next month |
andrewboyson | 26:0421132e6eaf | 191 | *pDaysLeft -= daysInMonth; |
andrewboyson | 26:0421132e6eaf | 192 | ++*pMonth; |
andrewboyson | 26:0421132e6eaf | 193 | } |
andrewboyson | 26:0421132e6eaf | 194 | } |
andrewboyson | 26:0421132e6eaf | 195 | static void timeToTm(time_t t, struct tm* ptm, bool local) |
andrewboyson | 26:0421132e6eaf | 196 | { |
andrewboyson | 26:0421132e6eaf | 197 | //Extract the seconds, minutes, hours and days from the time_t t |
andrewboyson | 26:0421132e6eaf | 198 | div_t divres; |
andrewboyson | 26:0421132e6eaf | 199 | divres = div( t, 60); int seconds = divres.rem; |
andrewboyson | 26:0421132e6eaf | 200 | divres = div(divres.quot, 60); int minutes = divres.rem; |
andrewboyson | 26:0421132e6eaf | 201 | divres = div(divres.quot, 24); int hours = divres.rem; |
andrewboyson | 26:0421132e6eaf | 202 | int daysLeft = divres.quot; |
andrewboyson | 26:0421132e6eaf | 203 | |
andrewboyson | 26:0421132e6eaf | 204 | //Add a year at a time while there is more than a year of days left |
andrewboyson | 26:0421132e6eaf | 205 | int year = 70; //Unix epoch is 1970 |
andrewboyson | 26:0421132e6eaf | 206 | int dayOfWeek = 4; //1 Jan 1970 is a Thursday |
andrewboyson | 26:0421132e6eaf | 207 | addYears(&year, &dayOfWeek, &daysLeft); |
andrewboyson | 26:0421132e6eaf | 208 | |
andrewboyson | 26:0421132e6eaf | 209 | //Days left contains the days left from the start (1 Jan) of the current year |
andrewboyson | 26:0421132e6eaf | 210 | int dayOfYear = daysLeft; |
andrewboyson | 26:0421132e6eaf | 211 | dayOfWeek += daysLeft; |
andrewboyson | 26:0421132e6eaf | 212 | dayOfWeek %= 7; |
andrewboyson | 26:0421132e6eaf | 213 | |
andrewboyson | 26:0421132e6eaf | 214 | //Add a month at a time while there is more than a month of days left |
andrewboyson | 26:0421132e6eaf | 215 | int month = 0; |
andrewboyson | 26:0421132e6eaf | 216 | addMonths(year, &month, &daysLeft); |
andrewboyson | 26:0421132e6eaf | 217 | |
andrewboyson | 26:0421132e6eaf | 218 | //Days left contains the days left from the start (1st) of the current month |
andrewboyson | 26:0421132e6eaf | 219 | int dayOfMonth = daysLeft + 1; |
andrewboyson | 26:0421132e6eaf | 220 | |
andrewboyson | 26:0421132e6eaf | 221 | //Deal with local time offsets |
andrewboyson | 26:0421132e6eaf | 222 | int dst; |
andrewboyson | 26:0421132e6eaf | 223 | if (local) |
andrewboyson | 26:0421132e6eaf | 224 | { |
andrewboyson | 26:0421132e6eaf | 225 | //Work out if Daylight Saving Time applies |
andrewboyson | 26:0421132e6eaf | 226 | dst = isDst(year, month, dayOfMonth, dayOfWeek, hours); |
andrewboyson | 26:0421132e6eaf | 227 | |
andrewboyson | 26:0421132e6eaf | 228 | //Adjust for the timezone |
andrewboyson | 26:0421132e6eaf | 229 | hours += dst ? DST_OFFSET : STD_OFFSET; |
andrewboyson | 26:0421132e6eaf | 230 | normalise(&hours, &dayOfWeek, &dayOfMonth, &month, &dayOfYear, &year); |
andrewboyson | 26:0421132e6eaf | 231 | } |
andrewboyson | 26:0421132e6eaf | 232 | else |
andrewboyson | 26:0421132e6eaf | 233 | { |
andrewboyson | 26:0421132e6eaf | 234 | dst = -1; |
andrewboyson | 26:0421132e6eaf | 235 | } |
andrewboyson | 26:0421132e6eaf | 236 | |
andrewboyson | 26:0421132e6eaf | 237 | //Set up the broken time TM structure |
andrewboyson | 26:0421132e6eaf | 238 | ptm->tm_sec = seconds; // 00 --> 59 |
andrewboyson | 26:0421132e6eaf | 239 | ptm->tm_min = minutes; // 00 --> 59 |
andrewboyson | 26:0421132e6eaf | 240 | ptm->tm_hour = hours; // 00 --> 23 |
andrewboyson | 26:0421132e6eaf | 241 | ptm->tm_mday = dayOfMonth; // 01 --> 31 |
andrewboyson | 26:0421132e6eaf | 242 | ptm->tm_mon = month; // 00 --> 11 |
andrewboyson | 26:0421132e6eaf | 243 | ptm->tm_year = year; // Years since 1900 |
andrewboyson | 26:0421132e6eaf | 244 | ptm->tm_wday = dayOfWeek; // 0 --> 6 where 0 == Sunday |
andrewboyson | 26:0421132e6eaf | 245 | ptm->tm_yday = dayOfYear; // 0 --> 365 |
andrewboyson | 26:0421132e6eaf | 246 | ptm->tm_isdst = dst; // +ve if DST, 0 if not DSTime, -ve if the information is not available. Note that 'true' evaluates to +1. |
andrewboyson | 26:0421132e6eaf | 247 | } |
andrewboyson | 26:0421132e6eaf | 248 | void TimeToTmUtc(time_t time, struct tm* ptm) |
andrewboyson | 26:0421132e6eaf | 249 | { |
andrewboyson | 26:0421132e6eaf | 250 | timeToTm(time, ptm, false); |
andrewboyson | 26:0421132e6eaf | 251 | } |
andrewboyson | 26:0421132e6eaf | 252 | void TimeToTmLocal(time_t time, struct tm* ptm) |
andrewboyson | 26:0421132e6eaf | 253 | { |
andrewboyson | 26:0421132e6eaf | 254 | timeToTm(time, ptm, true); |
andrewboyson | 26:0421132e6eaf | 255 | } |
andrewboyson | 26:0421132e6eaf | 256 | time_t TimeFromTmUtc(struct tm* ptm) |
andrewboyson | 26:0421132e6eaf | 257 | { |
andrewboyson | 26:0421132e6eaf | 258 | int days = 0; |
andrewboyson | 26:0421132e6eaf | 259 | |
andrewboyson | 26:0421132e6eaf | 260 | for (int y = 70; y < ptm->tm_year; y++) days += isLeapYear(y) ? 366 : 365; |
andrewboyson | 26:0421132e6eaf | 261 | |
andrewboyson | 26:0421132e6eaf | 262 | days += ptm->tm_yday; |
andrewboyson | 26:0421132e6eaf | 263 | |
andrewboyson | 26:0421132e6eaf | 264 | return days * 86400 + |
andrewboyson | 26:0421132e6eaf | 265 | ptm->tm_hour * 3600 + |
andrewboyson | 26:0421132e6eaf | 266 | ptm->tm_min * 60 + |
andrewboyson | 26:0421132e6eaf | 267 | ptm->tm_sec; |
andrewboyson | 26:0421132e6eaf | 268 | } |
andrewboyson | 26:0421132e6eaf | 269 | int TimePeriodBetween(struct tm* ptmLater, struct tm* ptmEarlier) |
andrewboyson | 26:0421132e6eaf | 270 | { |
andrewboyson | 26:0421132e6eaf | 271 | int days = 0; |
andrewboyson | 26:0421132e6eaf | 272 | |
andrewboyson | 26:0421132e6eaf | 273 | if (ptmLater->tm_year > ptmEarlier->tm_year) for (int y = ptmEarlier->tm_year; y < ptmLater->tm_year; y++) days += isLeapYear(y) ? 366 : 365; |
andrewboyson | 26:0421132e6eaf | 274 | else for (int y = ptmEarlier->tm_year; y > ptmLater->tm_year; y--) days -= isLeapYear(y) ? 366 : 365; |
andrewboyson | 26:0421132e6eaf | 275 | |
andrewboyson | 26:0421132e6eaf | 276 | days += ptmLater->tm_yday - ptmEarlier->tm_yday; |
andrewboyson | 26:0421132e6eaf | 277 | |
andrewboyson | 26:0421132e6eaf | 278 | return days * 86400 + |
andrewboyson | 26:0421132e6eaf | 279 | (ptmLater->tm_hour - ptmEarlier->tm_hour) * 3600 + |
andrewboyson | 26:0421132e6eaf | 280 | (ptmLater->tm_min - ptmEarlier->tm_min ) * 60 + |
andrewboyson | 26:0421132e6eaf | 281 | (ptmLater->tm_sec - ptmEarlier->tm_sec ); |
andrewboyson | 26:0421132e6eaf | 282 | } |
andrewboyson | 26:0421132e6eaf | 283 | |
andrewboyson | 26:0421132e6eaf | 284 | void TimeTmUtcToLocal(struct tm* ptm) |
andrewboyson | 26:0421132e6eaf | 285 | { |
andrewboyson | 26:0421132e6eaf | 286 | //Establish DST |
andrewboyson | 26:0421132e6eaf | 287 | ptm->tm_isdst = isDst(ptm->tm_year, ptm->tm_mon, ptm->tm_mday, ptm->tm_wday, ptm->tm_hour); |
andrewboyson | 26:0421132e6eaf | 288 | |
andrewboyson | 26:0421132e6eaf | 289 | //Adjust for the timezone |
andrewboyson | 26:0421132e6eaf | 290 | ptm->tm_hour += ptm->tm_isdst ? DST_OFFSET : STD_OFFSET; |
andrewboyson | 26:0421132e6eaf | 291 | normalise(&ptm->tm_hour, &ptm->tm_wday, &ptm->tm_mday, &ptm->tm_mon, &ptm->tm_yday, &ptm->tm_year); |
andrewboyson | 26:0421132e6eaf | 292 | } |
andrewboyson | 26:0421132e6eaf | 293 | |
andrewboyson | 26:0421132e6eaf | 294 | void TimeAsciiDateTimeToTm(const char* pDate, const char* pTime, struct tm* ptm) // Convert compile time to system time |
andrewboyson | 26:0421132e6eaf | 295 | { |
andrewboyson | 26:0421132e6eaf | 296 | //__DATE__ The string constant contains eleven characters and looks like "Feb 12 1996". If the day of the month is less than 10, it is padded with a space on the left. |
andrewboyson | 26:0421132e6eaf | 297 | char month[5]; |
andrewboyson | 26:0421132e6eaf | 298 | sscanf(pDate, "%s %d %d", month, &ptm->tm_mday, &ptm->tm_year); ptm->tm_year -= 1900; |
andrewboyson | 26:0421132e6eaf | 299 | |
andrewboyson | 26:0421132e6eaf | 300 | // Find where month is in month_names. Deduce month value. |
andrewboyson | 26:0421132e6eaf | 301 | static const char month_names[] = "JanFebMarAprMayJunJulAugSepOctNovDec"; |
andrewboyson | 26:0421132e6eaf | 302 | ptm->tm_mon = (strstr(month_names, month) - month_names) / 3; |
andrewboyson | 26:0421132e6eaf | 303 | |
andrewboyson | 26:0421132e6eaf | 304 | //__TIME__ The string constant contains eight characters and looks like "23:59:01". |
andrewboyson | 26:0421132e6eaf | 305 | sscanf(pTime, "%2d %*c %2d %*c %2d", &ptm->tm_hour, &ptm->tm_min, &ptm->tm_sec); |
andrewboyson | 26:0421132e6eaf | 306 | |
andrewboyson | 26:0421132e6eaf | 307 | //Fill the day of week and the day of year part of the tm structure |
andrewboyson | 26:0421132e6eaf | 308 | calculateDayOfYearAndWeek(ptm->tm_year, ptm->tm_mon, ptm->tm_mday, &ptm->tm_yday, &ptm->tm_wday); |
andrewboyson | 26:0421132e6eaf | 309 | } |