Bertrik Sikken | 727e8aa | 2012-03-08 21:21:31 +0100 | [diff] [blame] | 1 | /*************************************************************************** |
| 2 | * __________ __ ___. |
| 3 | * Open \______ \ ____ ____ | | _\_ |__ _______ ___ |
| 4 | * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ / |
| 5 | * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < < |
| 6 | * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \ |
| 7 | * \/ \/ \/ \/ \/ |
| 8 | * $Id$ |
| 9 | * |
| 10 | * Copyright (C) 2012 by Bertrik Sikken |
| 11 | * |
| 12 | * Based on code from: rtc_as3514.c |
| 13 | * Copyright (C) 2007 by Barry Wardell |
| 14 | * |
| 15 | * This program is free software; you can redistribute it and/or |
| 16 | * modify it under the terms of the GNU General Public License |
| 17 | * as published by the Free Software Foundation; either version 2 |
| 18 | * of the License, or (at your option) any later version. |
| 19 | * |
| 20 | * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY |
| 21 | * KIND, either express or implied. |
| 22 | * |
| 23 | ****************************************************************************/ |
| 24 | #include <stdbool.h> |
Rafaël Carré | d2aafd1 | 2012-03-11 17:15:56 -0400 | [diff] [blame^] | 25 | #include <stdint.h> |
Bertrik Sikken | 727e8aa | 2012-03-08 21:21:31 +0100 | [diff] [blame] | 26 | #include "time.h" |
| 27 | |
| 28 | #define MINUTE_SECONDS 60 |
| 29 | #define HOUR_SECONDS 3600 |
| 30 | #define DAY_SECONDS 86400 |
| 31 | #define WEEK_SECONDS 604800 |
| 32 | #define YEAR_SECONDS 31536000 |
| 33 | #define LEAP_YEAR_SECONDS 31622400 |
| 34 | |
| 35 | /* Days in each month */ |
Rafaël Carré | d2aafd1 | 2012-03-11 17:15:56 -0400 | [diff] [blame^] | 36 | static uint8_t days_in_month[] = |
Bertrik Sikken | 727e8aa | 2012-03-08 21:21:31 +0100 | [diff] [blame] | 37 | {31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}; |
| 38 | |
| 39 | static inline bool is_leapyear(int year) |
| 40 | { |
| 41 | return (((year%4)==0) && (((year%100)!=0) || ((year%400)==0))); |
| 42 | } |
| 43 | |
| 44 | struct tm *gmtime(const time_t *timep) |
| 45 | { |
| 46 | static struct tm time; |
| 47 | return gmtime_r(timep, &time); |
| 48 | } |
| 49 | |
| 50 | struct tm *gmtime_r(const time_t *timep, struct tm *tm) |
| 51 | { |
| 52 | time_t seconds = *timep; |
| 53 | int year, i, mday, hour, min; |
| 54 | |
| 55 | /* weekday */ |
| 56 | tm->tm_wday = ((seconds % WEEK_SECONDS) / DAY_SECONDS + 4) % 7; |
| 57 | |
| 58 | /* Year */ |
| 59 | year = 1970; |
| 60 | while (seconds >= LEAP_YEAR_SECONDS) |
| 61 | { |
| 62 | if (is_leapyear(year)){ |
| 63 | seconds -= LEAP_YEAR_SECONDS; |
| 64 | } else { |
| 65 | seconds -= YEAR_SECONDS; |
| 66 | } |
| 67 | |
| 68 | year++; |
| 69 | } |
| 70 | |
| 71 | if (is_leapyear(year)) { |
| 72 | days_in_month[1] = 29; |
| 73 | } else { |
| 74 | days_in_month[1] = 28; |
| 75 | if(seconds>YEAR_SECONDS){ |
| 76 | year++; |
| 77 | seconds -= YEAR_SECONDS; |
| 78 | } |
| 79 | } |
| 80 | tm->tm_year = year%100 + 100; |
| 81 | |
| 82 | /* Month */ |
| 83 | for (i = 0; i < 12; i++) |
| 84 | { |
| 85 | if (seconds < days_in_month[i]*DAY_SECONDS){ |
| 86 | tm->tm_mon = i; |
| 87 | break; |
| 88 | } |
| 89 | |
| 90 | seconds -= days_in_month[i]*DAY_SECONDS; |
| 91 | } |
| 92 | |
| 93 | /* Month Day */ |
| 94 | mday = seconds/DAY_SECONDS; |
| 95 | seconds -= mday*DAY_SECONDS; |
| 96 | tm->tm_mday = mday + 1; /* 1 ... 31 */ |
| 97 | |
| 98 | /* Hour */ |
| 99 | hour = seconds/HOUR_SECONDS; |
| 100 | seconds -= hour*HOUR_SECONDS; |
| 101 | tm->tm_hour = hour; |
| 102 | |
| 103 | /* Minute */ |
| 104 | min = seconds/MINUTE_SECONDS; |
| 105 | seconds -= min*MINUTE_SECONDS; |
| 106 | tm->tm_min = min; |
| 107 | |
| 108 | /* Second */ |
| 109 | tm->tm_sec = seconds; |
| 110 | |
| 111 | return tm; |
| 112 | } |
| 113 | |