/* * Copyright 2024 Google LLC * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ #include "clar.h" #include "services/common/clock.h" #include "services/normal/timezone_database.h" #include "services/normal/filesystem/pfs.h" #include "resource/resource_ids.auto.h" #include "flash_region/flash_region_s29vs.h" #include "resource/resource.h" #include "resource/resource_version.auto.h" // Fixture //////////////////////////////////////////////////////////////// #include "fixtures/load_test_resources.h" // Fakes //////////////////////////////////////////////////////////////// #include "fake_rtc.h" #include "fake_events.h" #include "fake_spi_flash.h" #include "fake_system_task.h" // Stubs //////////////////////////////////// #include "stubs_analytics.h" #include "stubs_hexdump.h" #include "stubs_language_ui.h" #include "stubs_logging.h" #include "stubs_mutex.h" #include "stubs_pbl_malloc.h" #include "stubs_prompt.h" #include "stubs_regular_timer.h" #include "stubs_serial.h" #include "stubs_session.h" #include "stubs_sleep.h" #include "stubs_system_reset.h" #include "stubs_task_watchdog.h" #include "stubs_memory_layout.h" static bool s_prefs_24h_style; #define TIMEZONE_FIXTURE_PATH "timezones" // Setup ///////////////////////// void test_clock__initialize(void) { // Setup resources fake_spi_flash_init(0, 0x1000000); pfs_init(false); load_resource_fixture_in_flash(RESOURCES_FIXTURE_PATH, SYSTEM_RESOURCES_FIXTURE_NAME, false); resource_init(); } extern void prv_update_time_info_and_generate_event(time_t *t, TimezoneInfo *tz_info); void clock_set_time(time_t t) { prv_update_time_info_and_generate_event(&t, NULL); } static void prv_clock_reset(int32_t gmtoff) { TimezoneInfo tzinfo = {{0}}; tzinfo.dst_id = 0; tzinfo.dst_start = tzinfo.dst_end = 0; tzinfo.tm_gmtoff = gmtoff; tzinfo.timezone_id = 0; rtc_set_timezone(&tzinfo); clock_init(); clock_set_24h_style(false); } static void prv_set_current_time(struct tm new_time) { time_t secs = mktime(&new_time); rtc_set_time(secs); } // Fakes /////////////////////////// void notifications_migrate_timezone(int utc_diff) { } void wakeup_migrate_timezone(int utc_diff) { } bool shell_prefs_get_clock_24h_style(void) { return s_prefs_24h_style; } void shell_prefs_set_clock_24h_style(bool is_24h_style) { s_prefs_24h_style = is_24h_style; } bool shell_prefs_is_timezone_source_manual(void) { return false; } void shell_prefs_set_timezone_source_manual(bool manual) { } int16_t shell_prefs_get_automatic_timezone_id(void) { return -1; } void shell_prefs_set_automatic_timezone_id(int16_t timezone_id) { } bool shell_prefs_get_language_english(void) { return false; } void shell_prefs_set_language_english(bool english) { } void sys_localtime_r(time_t const *t, struct tm *lcltime) { localtime_r(t, lcltime); } void sys_gmtime_r(time_t const *t, struct tm *lcltime) { gmtime_r(t, lcltime); } void launcher_task_add_callback(void (*callback)(void *data), void *data) { callback(data); } // Tests /////////////////////////// void test_clock__basic_no_timezone_set_time(void) { s_prefs_24h_style = false; fake_rtc_init(0, 0); rtc_timezone_clear(); clock_init(); static const time_t jan1st_noon_2005 = 1104580800; clock_set_time(jan1st_noon_2005); cl_assert_equal_i(rtc_get_time(), jan1st_noon_2005); } void test_clock__basic_timezone_gmtoffset(void) { s_prefs_24h_style = false; fake_rtc_init(0, 0); rtc_timezone_clear(); static const time_t jan1st_noon_2005 = 1104580800; static const int32_t min_gmtoff = -12 * SECONDS_PER_HOUR; static const int32_t max_gmtoff = 12 * SECONDS_PER_HOUR; static const int32_t gmtoff_slide = SECONDS_PER_MINUTE; TimezoneInfo tzinfo = {{0}}; strcpy(tzinfo.tm_zone, "UNK"); tzinfo.dst_id = 0; tzinfo.dst_start = tzinfo.dst_end = 0; tzinfo.timezone_id = -1; for (int32_t gmtoff = min_gmtoff; gmtoff <= max_gmtoff; gmtoff += gmtoff_slide) { prv_clock_reset(0); tzinfo.tm_gmtoff = gmtoff; rtc_set_timezone(&tzinfo); clock_init(); clock_set_time(jan1st_noon_2005); cl_assert_equal_i(rtc_get_time(), jan1st_noon_2005); cl_assert_equal_i(time_utc_to_local(rtc_get_time()), jan1st_noon_2005 + gmtoff); } } void test_clock__basic_timezone_dst(void) { s_prefs_24h_style = false; fake_rtc_init(0, 0); rtc_timezone_clear(); static const time_t jan1st_noon_2005 = 1104580800; static const int32_t min_dstoff = -12 * SECONDS_PER_HOUR; static const int32_t max_dstoff = 12 * SECONDS_PER_HOUR; static const int32_t dstoff_slide = SECONDS_PER_MINUTE; static const int32_t dstrange = SECONDS_PER_HOUR; TimezoneInfo tzinfo = {{0}}; strcpy(tzinfo.tm_zone, "UNK"); tzinfo.dst_id = 0; tzinfo.tm_gmtoff = 0; tzinfo.timezone_id = -1; for (int32_t dstoff = min_dstoff; dstoff <= max_dstoff; dstoff += dstoff_slide) { prv_clock_reset(0); tzinfo.dst_start = dstoff; tzinfo.dst_end = tzinfo.dst_start + dstrange; rtc_set_timezone(&tzinfo); clock_init(); clock_set_time(jan1st_noon_2005); cl_assert_equal_i(rtc_get_time(), jan1st_noon_2005); if (tzinfo.dst_start <= rtc_get_time() && rtc_get_time() < tzinfo.dst_end) { cl_assert_equal_i(time_utc_to_local(rtc_get_time()), jan1st_noon_2005 + time_get_dstoffset()); } else { cl_assert_equal_i(time_utc_to_local(rtc_get_time()), jan1st_noon_2005); } } } #define DST_ID_COUNT 36 static const time_t s_dst_correct_values[DST_ID_COUNT][3] = { /* No DST: 0 ~ 0, GMT+0 */ [ 0]={ 0, 0, 0 }, /* AN (New South Wales) [Australia/Sydney] Rule AN 2008 max - Apr Sun>=1 2:00s 0 S Rule AN 2008 max - Oct Sun>=1 2:00s 1:00 D Oct 4th 2014 16:00 UTC ~ Apr 4th 2015 16:00 UTC, GMT+10 */ [ 1]={ 1412438400, 1428163200, 10 * SECONDS_PER_HOUR }, /* AS (South Australia) [Australia/Adelaide] Rule AS 2008 max - Apr Sun>=1 2:00s 0 S Rule AS 2008 max - Oct Sun>=1 2:00s 1:00 D Oct 4th 2014 16:30 UTC ~ Apr 4th 2015 16:30 UTC, GMT+9.5 */ [ 2]={ 1412440200, 1428165000, 9.5 * SECONDS_PER_HOUR }, /* AT (Tasmania) [Australia/Hobart] Rule AT 2008 max - Apr Sun>=1 2:00s 0 S Rule AT 2001 max - Oct Sun>=1 2:00s 1:00 D Oct 4th 2014 16:00 UTC ~ Apr 4th 2015 16:00 UTC, GMT+10 */ [ 3]={ 1412438400, 1428163200, 10 * SECONDS_PER_HOUR }, /* AV (Victoria) [Australia/Melbourne] Rule AV 2008 max - Apr Sun>=1 2:00s 0 S Rule AV 2008 max - Oct Sun>=1 2:00s 1:00 D Oct 4th 2014 16:00 UTC ~ Apr 4th 2015 16:00 UTC, GMT+10 */ [ 4]={ 1412438400, 1428163200, 10 * SECONDS_PER_HOUR }, /* Azer (Azerbaijan) [Asia/Baku] * Azerbaijan has abandoned DST */ [ 5]={ 0, 0, 4 * SECONDS_PER_HOUR }, /* Brazil (Brazil) [America/Sao_Paulo] Rule Brazil 2008 max - Oct Sun>=15 0:00 1:00 S *Rule Brazil 2012 only - Feb Sun>=22 0:00 0 - *Rule Brazil 2013 2014 - Feb Sun>=15 0:00 0 - * THESE TWO RULES REPEAT FROM NOW ONWARDS Oct 19th 2014 03:00 UTC ~ Feb 22nd 2015 02:00 UTC, GMT-3 */ [ 6]={ 1413687600, 1424570400,-3 * SECONDS_PER_HOUR }, /* C-Eur (Central Europe) [Nowhere actually uses this anymore lol] Rule C-Eur 1981 max - Mar lastSun 2:00s 1:00 S Rule C-Eur 1996 max - Oct lastSun 2:00s 0 - * For all intents and purposes, this is the same as EU. Mar 29th 2015 01:00 UTC ~ Oct 25th 2015 01:00 UTC, GMT+1 */ [ 7]={ 1427590800, 1445734800, 1 * SECONDS_PER_HOUR }, /* Canada (Canada) [America/Toronto] Rule Canada 2007 max - Mar Sun>=8 2:00 1:00 D Rule Canada 2007 max - Nov Sun>=1 2:00 0 S Mar 8th 2015 07:00 UTC ~ Nov 1st 2015 06:00 UTC, GMT-5 */ [ 8]={ 1425798000, 1446357600,-5 * SECONDS_PER_HOUR }, /* Chatham (Chatham) [Pacific/Chatham] Rule Chatham 2007 max - Sep lastSun 2:45s 1:00 D Rule Chatham 2008 max - Apr Sun>=1 2:45s 0 S Sep 27th 2014 14:00 UTC ~ Apr 4th 2015 14:00 UTC, GMT+12.75 */ [ 9]={ 1411826400, 1428156000,12.75 * SECONDS_PER_HOUR }, /* ChileAQ (Chile Antarctica Bases) [Antarctica/Palmer] Rule Chile 2012 max - Apr Sun>=23 3:00u 0 - Rule Chile 2012 max - Sep Sun>=2 4:00u 1:00 S * ChileAQ is literally the same as Chile now. * From Chile: Actually, Chile no longer observes DST, so this is no longer used. Sep 7th 2014 04:00 UTC ~ Apr 26th 2015 03:00 UTC, GMT-4 */ [10]={ 0, 0,-4 * SECONDS_PER_HOUR }, /* Cuba (Cuba) [America/Havana] Rule Cuba 2012 max - Nov Sun>=1 0:00s 0 S Rule Cuba 2013 max - Mar Sun>=8 0:00s 1:00 D Mar 8th 2015 05:00 UTC ~ Nov 1st 2015 05:00 UTC, GMT-5 */ [11]={ 1425790800, 1446354000,-5 * SECONDS_PER_HOUR }, /* E-Eur (Eastern Europe) [Nowhere actually uses this anymore lol] [Europe/Sofia] Rule E-Eur 1981 max - Mar lastSun 0:00 1:00 S Rule E-Eur 1996 max - Oct lastSun 0:00 0 - * Similarly to C-Eur, this is no longer used, but this is actually different from EU. Mar 28th 2015 22:00 UTC ~ Oct 25th 2015 21:00 UTC, GMT+2 */ [12]={ 1427580000, 1445720400, 2 * SECONDS_PER_HOUR }, /* E-EurAsia (Georgia) [Nowhere actually uses this anymore lol] [Asia/Tbilisi] Rule E-EurAsia 1981 max - Mar lastSun 0:00 1:00 S Rule E-EurAsia 1996 max - Oct lastSun 0:00 0 - * Georgia gave up this time zone in 2005, and gave up DST entirely in 2006. Mar 28th 2015 20:00 UTC ~ Oct 24th 2015 19:00 UTC, GMT+4 */ [13]={ 1427572800, 1445713200, 4 * SECONDS_PER_HOUR }, /* EU (Europe) [Europe/Tirane] Rule EU 1981 max - Mar lastSun 1:00u 1:00 S Rule EU 1996 max - Oct lastSun 1:00u 0 - Mar 29th 2015 01:00 UTC ~ Oct 25th 2015 01:00 UTC, GMT+1 */ [14]={ 1427590800, 1445734800, 1 * SECONDS_PER_HOUR }, /* EUAsia (Europish Asia) [Asia/Nicosia] Rule EUAsia 1981 max - Mar lastSun 1:00u 1:00 S Rule EUAsia 1996 max - Oct lastSun 1:00u 0 - * This is literally the same as EU now. Mar 29th 2015 01:00 UTC ~ Oct 25th 2015 01:00 UTC, GMT+2 */ [15]={ 1427590800, 1445734800, 2 * SECONDS_PER_HOUR }, /* Egypt (Egypt) [Africa/Cairo] * Egypt has abandoned DST */ [16]={ 0, 0, 2 * SECONDS_PER_HOUR }, /* Fiji (Fiji Islands) [Pacific/Fiji] Rule Fiji 2014 max - Nov Sun>=1 2:00 1:00 S Rule Fiji 2015 max - Jan Sun>=18 3:00 0 - Nov 1st 2014 14:00 UTC ~ Jan 17th 2015 14:00 UTC, GMT+12 */ [17]={ 1414850400, 1421503200,12 * SECONDS_PER_HOUR }, /* Haiti (Haiti) [America/Port-au-Prince] * Haiti has abandoned DST */ [18]={ 0, 0,-5 * SECONDS_PER_HOUR }, /* Jordan (Jordan) [Asia/Amman] Rule Jordan 2014 max - Mar lastThu 24:00 1:00 S Rule Jordan 2014 max - Oct lastFri 0:00s 0 - Mar 26th 2015 22:00 UTC ~ Oct 29th 2015 22:00 UTC, GMT+2 */ [19]={ 1427407200, 1446156000, 2 * SECONDS_PER_HOUR }, /* LH (Lord Howe Island) [Australia/Lord_Howe] Rule LH 2008 max - Apr Sun>=1 2:00 0 S Rule LH 2008 max - Oct Sun>=1 2:00 0:30 D Oct 4th 2014 15:30 UTC ~ Apr 4th 2015 15:00 UTC, GMT+10.5 */ [20]={ 1412436600, 1428159600,10.5 * SECONDS_PER_HOUR }, /* Lebanon (Lebanon) [Asia/Beirut] Rule Lebanon 1993 max - Mar lastSun 0:00 1:00 S Rule Lebanon 1999 max - Oct lastSun 0:00 0 - Mar 28th 2015 22:00 UTC ~ Oct 24th 2015 21:00 UTC, GMT+2 */ [21]={ 1427580000, 1445720400, 2 * SECONDS_PER_HOUR }, /* Mexico (Mexico) [America/Mexico_City] Rule Mexico 2002 max - Apr Sun>=1 2:00 1:00 D Rule Mexico 2002 max - Oct lastSun 2:00 0 S Apr 5th 2015 08:00 UTC ~ Oct 25th 2015 07:00 UTC, GMT-6 */ [22]={ 1428220800, 1445756400,-6 * SECONDS_PER_HOUR }, /* Morocco (Morocco) [Africa/Casablanca] Rule Azer 1997 max - Mar lastSun 4:00 1:00 S Rule Azer 1997 max - Oct lastSun 5:00 0 - * TODO: * At least as insane as Egypt, without the possibility of parole. Mar 29th 2015 02:00 UTC ~ Oct 25th 2015 02:00 UTC, GMT+0 */ [23]={ 1427594400, 1445738400, 0 * SECONDS_PER_HOUR }, /* NZ (New Zealand) [Pacific/Auckland] Rule NZ 2007 max - Sep lastSun 2:00s 1:00 D Rule NZ 2008 max - Apr Sun>=1 2:00s 0 S Sep 27th 2014 14:00 UTC ~ Apr 4th 2015 14:00 UTC, GMT+12 */ [24]={ 1411826400, 1428156000,12 * SECONDS_PER_HOUR }, /* Namibia (Namibia) [Africa/Windhoek] Rule Namibia 1994 max - Sep Sun>=1 2:00 1:00 S Rule Namibia 1995 max - Apr Sun>=1 2:00 0 - Sep 7th 2014 01:00 UTC ~ Apr 5th 2015 00:00 UTC, GMT+1 */ [25]={ 1410051600, 1428192000, 1 * SECONDS_PER_HOUR }, /* Palestine (Gaza/West Bank) [Asia/Gaza] Rule Palestine 2016 max - Mar lastSat 1:00 1:00 S Rule Palestine 2016 max - Oct lastSat 1:00 0 - Mar 27th 2015 23:00 UTC ~ Sep 24th 2015 21:00 UTC, GMT+2 */ [26]={ 1427497200, 1446242400, 2 * SECONDS_PER_HOUR }, /* Para (Paraguay) [America/Asuncion] Rule Para 2010 max - Oct Sun>=1 0:00 1:00 S Rule Para 2013 max - Mar Sun>=22 0:00 0 - Oct 5th 2014 04:00 UTC ~ Mar 22nd 2015 03:00 UTC, GMT-4 */ [27]={ 1412481600, 1426993200,-4 * SECONDS_PER_HOUR }, /* RussiaAsia (Some Asian Russian areas) [Nowhere uses this anymore] [Asia/Yerevan] Rule RussiaAsia 1993 max - Mar lastSun 2:00s 1:00 S Rule RussiaAsia 1996 max - Oct lastSun 2:00s 0 - * Armenia gave this up in 2012 Mar 28th 2015 22:00 UTC ~ Oct 24th 2015 22:00 UTC, GMT+4 */ [28]={ 0, 0, 4 * SECONDS_PER_HOUR }, /* Syria (Syria) [Asia/Damascus] Rule Syria 2012 max - Mar lastFri 0:00 1:00 S Rule Syria 2009 max - Oct lastFri 0:00 0 - Mar 26th 2015 22:00 UTC ~ Oct 29th 2015 21:00 UTC, GMT+2 */ [29]={ 1427407200, 1446152400, 2 * SECONDS_PER_HOUR }, /* Thule (Thule Air Base) [America/Thule] Rule Thule 2007 max - Mar Sun>=8 2:00 1:00 D Rule Thule 2007 max - Nov Sun>=1 2:00 0 S Mar 8th 2015 06:00 UTC ~ Nov 1st 2015 05:00 UTC, GMT-4 */ [30]={ 1425794400, 1446354000,-4 * SECONDS_PER_HOUR }, /* US (United States) [America/Los_Angeles] Rule US 2007 max - Mar Sun>=8 2:00 1:00 D Rule US 2007 max - Nov Sun>=1 2:00 0 S Mar 8th 2015 10:00 UTC ~ Nov 1st 2015 09:00 UTC, GMT-8 */ [31]={ 1425808800, 1446368400,-8 * SECONDS_PER_HOUR }, /* Uruguay (Uruguay) [America/Montevideo] * Uruguay has abandoned DST */ [32]={ 0, 0,-3 * SECONDS_PER_HOUR }, /* W-Eur (Western Europe) [Nowhere uses this anymore] [Europe/Lisbon] Rule W-Eur 1981 max - Mar lastSun 1:00s 1:00 S Rule W-Eur 1996 max - Oct lastSun 1:00s 0 - * Similarly to C-Eur, this is no longer used, but this is actually different from EU. Mar 29th 2015 00:00 UTC ~ Oct 25th 2015 01:00 UTC, GMT+0 */ [33]={ 1427590800, 1445734800, 0 * SECONDS_PER_HOUR }, /* WS (Western Samoa) [Pacific/Apia] Rule WS 2012 max - Apr Sun>=1 4:00 0 S Rule WS 2012 max - Sep lastSun 3:00 1 D Sep 27th 2014 14:00 UTC ~ Apr 4th 2015 14:00 UTC, GMT+13 */ [34]={ 1411826400, 1428156000,13 * SECONDS_PER_HOUR }, /* Zion (Israel) [Asia/Jerusalem] Rule Zion 2013 max - Mar Fri>=23 2:00 1:00 D Rule Zion 2013 max - Oct lastSun 2:00 0 S Mar 27th 2015 00:00 UTC ~ Oct 24th 2015 23:00 UTC, GMT+2 */ [35]={ 1427414400, 1445727600, 2 * SECONDS_PER_HOUR }, }; void prv_update_dstrule_timestamps_by_dstzone_id(TimezoneInfo *tz_info, time_t utc_time); void test_clock__dstzone_rule_check(void) { s_prefs_24h_style = false; fake_rtc_init(0, 0); rtc_timezone_clear(); clock_init(); static const time_t jan1st_noon_2015 = 1420113600; for (int dstid = 0; dstid < DST_ID_COUNT; dstid++) { TimezoneInfo tz_info = { .dst_id = dstid, .tm_gmtoff = s_dst_correct_values[dstid][2] }; prv_update_dstrule_timestamps_by_dstzone_id(&tz_info, jan1st_noon_2015); if (tz_info.dst_start != s_dst_correct_values[dstid][0]) { printf("start [%d] tz_info: %ld s_dst_correct_values: %ld\n", dstid, tz_info.dst_start, s_dst_correct_values[dstid][0]); } if (tz_info.dst_end != s_dst_correct_values[dstid][1]) { printf(" end [%d] tz_info: %ld s_dst_correct_values: %ld\n", dstid, tz_info.dst_end, s_dst_correct_values[dstid][1]); } cl_check(tz_info.dst_start == s_dst_correct_values[dstid][0]); cl_check(tz_info.dst_end == s_dst_correct_values[dstid][1]); } } void test_clock__next_monday(void) { struct tm jan_1 = { .tm_sec = 0, // 0 seconds after the minute .tm_min = 0, // 0 minutes after the hour .tm_hour = 0, // 0 hours since midnight .tm_mday = 1, // 1st day of the month .tm_mon = 0, // January .tm_year = 2014 - 1900, .tm_isdst = 0, }; // next Monday (the 6th) at 17:30 struct tm jan_6 = { .tm_sec = 0, // 0 seconds after the minute .tm_min = 30, // 30 minutes after the hour .tm_hour = 17, // 17 hours since midnight .tm_mday = 6, // 6st day of the month .tm_mon = 0, // January .tm_year = 2014 - 1900, .tm_isdst = 0, }; // DST info for US/Canada 2014 TimezoneInfo tz_info = { .dst_start = 1394330400, // Sun, 09 Mar 2014 02:00 .dst_end = 1414893600// Sun, 02 Nov 2014 02:00 }; time_util_update_timezone(&tz_info); prv_set_current_time(jan_1); cl_assert_equal_i(clock_to_timestamp(MONDAY, 17, 30), mktime(&jan_6)); } void test_clock__clock_to_timestamp(void) { s_prefs_24h_style = false; fake_rtc_init(0, 0); rtc_timezone_clear(); static const time_t jan1st_noon_2005 = 1104580800; static const int32_t min_gmtoff = -12 * SECONDS_PER_HOUR; static const int32_t max_gmtoff = 12 * SECONDS_PER_HOUR; static const int32_t gmtoff_slide = SECONDS_PER_MINUTE; TimezoneInfo tzinfo = {{0}}; tzinfo.dst_id = 0; tzinfo.dst_start = tzinfo.dst_end = 0; tzinfo.timezone_id = 0; for (int32_t gmtoff = min_gmtoff; gmtoff <= max_gmtoff; gmtoff += gmtoff_slide) { prv_clock_reset(0); tzinfo.tm_gmtoff = gmtoff; rtc_set_timezone(&tzinfo); clock_init(); clock_set_time(jan1st_noon_2005); cl_assert_equal_i(rtc_get_time(), jan1st_noon_2005); time_t t = rtc_get_time(); struct tm now; localtime_r(&t, &now); time_t timestamp = clock_to_timestamp(TODAY, now.tm_hour, now.tm_min + 1); cl_assert_equal_i(timestamp, t + 60); } } void test_clock__cross_dst(void) { struct tm oct_31 = { .tm_sec = 0, .tm_min = 59, .tm_hour = 23, .tm_mday = 31, .tm_mon = 9, // Oct .tm_year = 2015 - 1900, .tm_isdst = 1, .tm_gmtoff = -5 * SECONDS_PER_HOUR, }; struct tm nov_7 = { .tm_sec = 0, .tm_min = 15, .tm_hour = 0, .tm_mday = 7, .tm_mon = 10, // Nov .tm_year = 2015 - 1900, .tm_isdst = 0, // Crossing daylight savings time barrier! .tm_gmtoff = -5 * SECONDS_PER_HOUR, }; // DST info for US/Canada 2015 TimezoneInfo tz_info = { .dst_start = 1425780000, // Sun, 08 Mar 2015 02:00 .dst_end = 1446343200, // Sun, 01 Nov 2015 02:00 .tm_gmtoff = -5 * SECONDS_PER_HOUR, }; time_util_update_timezone(&tz_info); prv_set_current_time(oct_31); cl_assert_equal_i(clock_to_timestamp(SATURDAY, 0, 15), mktime(&nov_7)); } void test_clock__today(void) { struct tm may_30 = { .tm_sec = 0, .tm_min = 59, .tm_hour = 7, .tm_mday = 30, .tm_mon = 4, // May .tm_year = 2016 - 1900, .tm_isdst = 1, .tm_gmtoff = -5 * SECONDS_PER_HOUR, }; struct tm may_31 = { .tm_sec = 0, .tm_min = 0, .tm_hour = 5, .tm_mday = 31, .tm_mon = 4, // May .tm_year = 2016 - 1900, .tm_isdst = 1, .tm_gmtoff = -5 * SECONDS_PER_HOUR, }; // DST info for US/Canada 2016 TimezoneInfo tz_info = { .dst_id = 0, .dst_start = 1457834400, // Sun, 13 Mar 2016 02:00 .dst_end = 1478397600, // Sun, 06 Nov 2016 02:00 .tm_gmtoff = -5 * SECONDS_PER_HOUR, }; time_util_update_timezone(&tz_info); prv_set_current_time(may_30); cl_assert_equal_i(clock_to_timestamp(TODAY, 5, 0), mktime(&may_31)); } void test_clock__time_until_one_hour_relative(void) { char time_buf[64]; const int jun10th_noon_2015 = 1433937600; prv_clock_reset(0); rtc_set_time(jun10th_noon_2015); // Our test event is at June 10th 2015, 14:00:00 // Now + two hours const int event_time = jun10th_noon_2015 + (2 * SECONDS_PER_HOUR); // if the event is in 1+ hours, then show the actual time instead of "In X hours" const int MAX_RELATIVE_HRS = 1; // June 10th 2015, 12:00:00 (T-02:00:00) rtc_set_time(jun10th_noon_2015); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s(" 2:00 PM", time_buf); // June 8th 2015, 14:00:00 (T-48:00:00) rtc_set_time(event_time - SECONDS_PER_DAY - (24 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Wed, 2:00 PM", time_buf); // June 8th 2015, 23:59:58 (T-38:00:02) rtc_set_time(event_time - SECONDS_PER_DAY - (14 * SECONDS_PER_HOUR) - 2); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Wed, 2:00 PM", time_buf); // June 8th 2015, 23:59:59 (T-38:00:01) rtc_set_time(event_time - SECONDS_PER_DAY - (14 * SECONDS_PER_HOUR) - 1); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Wed, 2:00 PM", time_buf); // June 9th 2015, 14:00:00 (T-24:00:00) rtc_set_time(event_time - (24 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Wed, 2:00 PM", time_buf); // June 9th 2015, 23:59:58 (T-14:00:02) rtc_set_time(event_time - (14 * SECONDS_PER_HOUR) - 2); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Wed, 2:00 PM", time_buf); // June 9th 2015, 23:59:59 (T-14:00:01) rtc_set_time(event_time - (14 * SECONDS_PER_HOUR) - 1); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Wed, 2:00 PM", time_buf); // June 10th 2015, 00:00:00 (T-14:00:00) rtc_set_time(event_time - (14 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s(" 2:00 PM", time_buf); // June 10th 2015, 00:00:01 (T-13:59:59) rtc_set_time(event_time - (14 * SECONDS_PER_HOUR) + 1); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s(" 2:00 PM", time_buf); // June 10th 2015, 12:59:59 (T-01:00:01) rtc_set_time(event_time - (1 * SECONDS_PER_HOUR) - 1); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s(" 2:00 PM", time_buf); // June 10th 2015, 13:00:00 (T-01:00:00) rtc_set_time(event_time - (1 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 1 H", time_buf); // June 10th 2015, 13:00:01 (T-00:59:59) rtc_set_time(event_time - (1 * SECONDS_PER_HOUR) + 1); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 1 H", time_buf); // June 10th 2015, 13:00:59 (T-00:59:01) rtc_set_time(event_time - (1 * SECONDS_PER_HOUR) + 59); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 1 H", time_buf); // June 10th 2015, 13:01:00 (T-00:59:00) rtc_set_time(event_time - (59 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 59 MIN", time_buf); // June 10th 2015, 13:01:59 (T-00:58:01) rtc_set_time(event_time - (58 * SECONDS_PER_MINUTE) - 1); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 59 MIN", time_buf); // June 10th 2015, 13:30:00 (T-00:30:00) rtc_set_time(event_time - (30 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 30 MIN", time_buf); // June 10th 2015, 13:30:29 (T-00:29:31) rtc_set_time(event_time - (30 * SECONDS_PER_MINUTE) + 29); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 30 MIN", time_buf); // June 10th 2015, 13:30:30 (T-00:29:30) rtc_set_time(event_time - (30 * SECONDS_PER_MINUTE) + 30); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 30 MIN", time_buf); // June 10th 2015, 13:30:59 (T-00:29:01) rtc_set_time(event_time - (30 * SECONDS_PER_MINUTE) + 59); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 30 MIN", time_buf); // June 10th 2015, 13:59:00 (T-00:01:00) rtc_set_time(event_time - (1 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 1 MIN", time_buf); // June 10th 2015, 13:59:59 (T-00:00:01) rtc_set_time(event_time - 1); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 1 MIN", time_buf); // June 10th 2015, 14:00:00 (T-00:00:00) rtc_set_time(event_time); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("NOW", time_buf); } void test_clock__time_until_twenty_four_hour_relative(void) { char time_buf[64]; const int jun10th_noon_2015 = 1433937600; prv_clock_reset(0); rtc_set_time(jun10th_noon_2015); // Our test event is at June 12th 2015, 12:00 // Now + two days const int event_time = jun10th_noon_2015 + (2 * SECONDS_PER_DAY); // if the event is in 24 hours on the same day, then show it. const int MAX_RELATIVE_HRS = 24; // June 10th 2015, 12:00:00 (T-48:00:00) rtc_set_time(jun10th_noon_2015); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Fri, 12:00 PM", time_buf); // June 5th 2015, 12:00:00 (T-7DAY-00:00:00) rtc_set_time(jun10th_noon_2015 - (7 * SECONDS_PER_DAY)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Jun 12, 12:00 PM", time_buf); // June 5th 2015, 12:00:01 (T-7DAY+00:00:01) rtc_set_time(jun10th_noon_2015 - (7 * SECONDS_PER_DAY) + 1); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Jun 12, 12:00 PM", time_buf); // June 10th 2015, 23:59:59 (T-2DAY+11:59:59) rtc_set_time(jun10th_noon_2015 + (12 * SECONDS_PER_HOUR) - 1); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Fri, 12:00 PM", time_buf); // June 11th 2015, 00:00:00 (T-1DAY-12:00:00) rtc_set_time(event_time - SECONDS_PER_DAY - (12 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Fri, 12:00 PM", time_buf); // June 11th 2015, 12:00:00 (T-24:00:00) rtc_set_time(event_time - SECONDS_PER_DAY); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Fri, 12:00 PM", time_buf); // June 11th 2015, 12:00:01 (T-23:59:59) rtc_set_time(event_time - SECONDS_PER_DAY + 1); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Fri, 12:00 PM", time_buf); // June 11th 2015, 23:59:29 (T-12:00:31) rtc_set_time(event_time - (12 * SECONDS_PER_HOUR) - 31); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Fri, 12:00 PM", time_buf); // June 11th 2015, 23:59:30 (T-12:00:30) rtc_set_time(event_time - (12 * SECONDS_PER_HOUR) - 30); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Fri, 12:00 PM", time_buf); // June 11th 2015, 23:59:59 (T-12:00:01) rtc_set_time(event_time - (12 * SECONDS_PER_HOUR) - 1); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Fri, 12:00 PM", time_buf); // June 12th 2015, 00:00:00 (T-12:00:00) rtc_set_time(event_time - (12 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 12 H", time_buf); // June 12th 2015, 00:00:01 (T-11:59:59) rtc_set_time(event_time - (12 * SECONDS_PER_HOUR) + 1); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 12 H", time_buf); // June 12th 2015, 00:29:29 (T-11:30:31) rtc_set_time(event_time - (12 * SECONDS_PER_HOUR) + (29 * SECONDS_PER_MINUTE) + 29); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 12 H", time_buf); // June 12th 2015, 00:29:30 (T-11:30:30) rtc_set_time(event_time - (12 * SECONDS_PER_HOUR) + (29 * SECONDS_PER_MINUTE) + 30); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 12 H", time_buf); // June 12th 2015, 00:29:59 (T-11:30:01) rtc_set_time(event_time - (12 * SECONDS_PER_HOUR) + (29 * SECONDS_PER_MINUTE) + 59); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 12 H", time_buf); // June 12th 2015, 00:30:00 (T-11:30:00) rtc_set_time(event_time - (12 * SECONDS_PER_HOUR) + (30 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 11 H", time_buf); // June 12th 2015, 00:30:01 (T-11:29:59) rtc_set_time(event_time - (12 * SECONDS_PER_HOUR) + (30 * SECONDS_PER_MINUTE) + 1); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 11 H", time_buf); // June 12th 2015, 00:59:59 (T-11:00:01) rtc_set_time(event_time - (11 * SECONDS_PER_HOUR) - 1); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 11 H", time_buf); // June 12th 2015, 01:00:00 (T-11:00:00) rtc_set_time(event_time - (11 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 11 H", time_buf); // June 12th 2015, 01:00:01 (T-10:59:59) rtc_set_time(event_time - (11 * SECONDS_PER_HOUR) + 1); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 11 H", time_buf); // June 12th 2015, 01:30:00 (T-10:30:00) rtc_set_time(event_time - (11 * SECONDS_PER_HOUR) + (30 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 10 H", time_buf); } void test_clock__time_past_two_hour_relative(void) { char time_buf[64]; const int jun10th_noon_2015 = 1433937600; prv_clock_reset(0); rtc_set_time(jun10th_noon_2015); // Our test event is at June 9th 2015, 12:00:00 // Now - one day const int event_time = jun10th_noon_2015 - SECONDS_PER_DAY; // if the event is within 2 hours, then show the actual time instead of "X hours ago" const int MAX_RELATIVE_HRS = 2; // June 9th 2015, 12:00:00 (T+00:00:00) rtc_set_time(event_time); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("NOW", time_buf); // June 9th 2015, 12:00:59 (T+00:00:59) rtc_set_time(event_time + (1 * SECONDS_PER_MINUTE) - 1); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("NOW", time_buf); // June 9th 2015, 12:01:00 (T+00:01:00) rtc_set_time(event_time + (1 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("1 MIN AGO", time_buf); // June 9th 2015, 12:05:00 (T+00:05:00) rtc_set_time(event_time + (5 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("5 MIN AGO", time_buf); // June 9th 2015, 12:10:00 (T+00:10:00) rtc_set_time(event_time + (10 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("10 MIN AGO", time_buf); // June 9th 2015, 12:10:00 (T+00:10:01) rtc_set_time(event_time + (10 * SECONDS_PER_MINUTE) + 1); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("10 MIN AGO", time_buf); // June 9th 2015, 12:10:30 (T+00:10:30) rtc_set_time(event_time + (10 * SECONDS_PER_MINUTE) + 30); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("10 MIN AGO", time_buf); // June 9th 2015, 12:10:59 (T+00:10:59) rtc_set_time(event_time + (10 * SECONDS_PER_MINUTE) + 59); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("10 MIN AGO", time_buf); // June 9th 2015, 12:59:29 (T+00:59:29) rtc_set_time(event_time + (59 * SECONDS_PER_MINUTE) + 29); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("59 MIN AGO", time_buf); // June 9th 2015, 12:59:30 (T+00:59:30) rtc_set_time(event_time + (59 * SECONDS_PER_MINUTE) + 30); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("59 MIN AGO", time_buf); // June 9th 2015, 12:59:58 (T+00:59:58) rtc_set_time(event_time + (59 * SECONDS_PER_MINUTE) + 58); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("59 MIN AGO", time_buf); // June 9th 2015, 12:59:59 (T+00:59:59) rtc_set_time(event_time + (59 * SECONDS_PER_MINUTE) + 59); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("59 MIN AGO", time_buf); // June 9th 2015, 13:00:00 (T+01:00:00) rtc_set_time(event_time + SECONDS_PER_HOUR); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("1 H AGO", time_buf); // June 9th 2015, 13:29:29 (T+01:29:29) rtc_set_time(event_time + SECONDS_PER_HOUR + (29 * SECONDS_PER_MINUTE) + 29); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("1 H AGO", time_buf); // June 9th 2015, 13:29:30 (T+01:29:30) rtc_set_time(event_time + SECONDS_PER_HOUR + (29 * SECONDS_PER_MINUTE) + 30); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("1 H AGO", time_buf); // June 9th 2015, 13:30:00 (T+01:30:00) rtc_set_time(event_time + SECONDS_PER_HOUR + (30 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("2 H AGO", time_buf); // June 9th 2015, 13:59:59 (T+01:59:59) rtc_set_time(event_time + SECONDS_PER_HOUR + (59 * SECONDS_PER_MINUTE) + 59); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("2 H AGO", time_buf); // June 9th 2015, 14:00:00 (T+02:00:00) rtc_set_time(event_time + (2 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("12:00 PM", time_buf); // June 9th 2015, 23:59:59 (T+11:59:59) rtc_set_time(event_time + (11 * SECONDS_PER_HOUR) + (59 * SECONDS_PER_MINUTE) + 59); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("12:00 PM", time_buf); // June 10th 2015, 00:00:00 (T+12:00:00) rtc_set_time(event_time + (12 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Yesterday, 12:00 PM", time_buf); // June 10th 2015, 11:00:00 (T+23:00:00) rtc_set_time(event_time + (23 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Yesterday, 12:00 PM", time_buf); // June 10th 2015, 13:00:00 (T+1DAY+01:00:00) rtc_set_time(event_time + SECONDS_PER_DAY + (1 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Yesterday, 12:00 PM", time_buf); // June 11th 2015, 13:00:00 (T+2DAY+01:00:00) rtc_set_time(event_time + (2 * SECONDS_PER_DAY) + (1 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Tue, 12:00 PM", time_buf); // June 16th 2015, 13:00:00 (T+7DAY+01:00:00) rtc_set_time(event_time + (7 * SECONDS_PER_DAY) + (1 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Jun 9, 12:00 PM", time_buf); } void test_clock__time_past_twenty_four_hour_relative(void) { char time_buf[64]; const int jun10th_noon_2015 = 1433937600; prv_clock_reset(0); rtc_set_time(jun10th_noon_2015); // Our test event is at June 9th 2015, 12:00:00 // Now - one day const int event_time = jun10th_noon_2015 - SECONDS_PER_DAY; // if the event is within 24 hours, then show the actual time instead of "X hours ago" const int MAX_RELATIVE_HRS = 24; // June 9th 2015, 13:30:00 (T+01:30:00) rtc_set_time(event_time + SECONDS_PER_HOUR + (30 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("2 H AGO", time_buf); // June 9th 2015, 13:59:59 (T+01:59:59) rtc_set_time(event_time + SECONDS_PER_HOUR + (59 * SECONDS_PER_MINUTE) + 59); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("2 H AGO", time_buf); // June 9th 2015, 14:00:00 (T+02:00:00) rtc_set_time(event_time + (2 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("2 H AGO", time_buf); // June 9th 2015, 23:59:59 (T+11:59:59) rtc_set_time(event_time + (11 * SECONDS_PER_HOUR) + (59 * SECONDS_PER_MINUTE) + 59); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("12 H AGO", time_buf); // June 10th 2015, 00:00:00 (T+12:00:00) rtc_set_time(event_time + (12 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Yesterday, 12:00 PM", time_buf); // June 10th 2015, 11:00:00 (T+23:00:00) rtc_set_time(event_time + (23 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Yesterday, 12:00 PM", time_buf); } void test_clock__time_12h_style(void) { char time_buf[64]; const int jun10th_noon_2015 = 1433937600; prv_clock_reset(0); rtc_set_time(jun10th_noon_2015); // Our test event is at June 9th 2015, 16:00:00 // Now - one day const int event_time = jun10th_noon_2015 - SECONDS_PER_DAY + (4 * SECONDS_PER_HOUR); // if the event is within 24 hours, then show the actual time instead of "X hours ago" const int MAX_RELATIVE_HRS = 13; clock_set_24h_style(false); // June 9th 2015, 17:00:00 (T+01:00:00) rtc_set_time(event_time + SECONDS_PER_HOUR); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("1 H AGO", time_buf); // June 9th 2015, 17:30:00 (T+01:30:00) rtc_set_time(event_time + SECONDS_PER_HOUR + (30 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("2 H AGO", time_buf); // June 9th 2015, 16:01:00 (T+00:01:00) rtc_set_time(event_time + (1 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("1 MIN AGO", time_buf); // June 9th 2015, 16:02:00 (T+00:02:00) rtc_set_time(event_time + (2 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("2 MIN AGO", time_buf); // June 9th 2015, 15:00:00 (T-01:00:00) rtc_set_time(event_time - (1 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 1 H", time_buf); // June 9th 2015, 14:00:00 (T-02:00:00) rtc_set_time(event_time - (2 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 2 H", time_buf); // June 9th 2015, 15:59:00 (T-00:01:00) rtc_set_time(event_time - (1 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 1 MIN", time_buf); // June 9th 2015, 15:58:00 (T-00:02:00) rtc_set_time(event_time - (2 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 2 MIN", time_buf); // June 10th 2015, 04:00:00 (T+12:00:00) rtc_set_time(event_time + (12 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Yesterday, 4:00 PM", time_buf); // June 9th 2015, 02:00:00 (T-14:00:00) rtc_set_time(event_time - (14 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s(" 4:00 PM", time_buf); // June 8th 2015, 16:00:00 (T-48:00:00) rtc_set_time(event_time - SECONDS_PER_DAY - (24 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Tue, 4:00 PM", time_buf); // June 16th 2015, 17:00:00 (T+7DAY+01:00:00) rtc_set_time(event_time + (7 * SECONDS_PER_DAY) + (1 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Jun 9, 4:00 PM", time_buf); } void test_clock__time_24h_style(void) { char time_buf[64]; const int jun10th_noon_2015 = 1433937600; prv_clock_reset(0); rtc_set_time(jun10th_noon_2015); // Our test event is at June 9th 2015, 16:00:00 // Now - one day const int event_time = jun10th_noon_2015 - SECONDS_PER_DAY + (4 * SECONDS_PER_HOUR); // if the event is within 24 hours, then show the actual time instead of "X hours ago" const int MAX_RELATIVE_HRS = 13; clock_set_24h_style(true); // June 9th 2015, 17:00:00 (T+01:00:00) rtc_set_time(event_time + SECONDS_PER_HOUR); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("1 H AGO", time_buf); // June 9th 2015, 17:30:00 (T+01:30:00) rtc_set_time(event_time + SECONDS_PER_HOUR + (30 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("2 H AGO", time_buf); // June 9th 2015, 16:01:00 (T+00:01:00) rtc_set_time(event_time + (1 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("1 MIN AGO", time_buf); // June 9th 2015, 16:02:00 (T+00:02:00) rtc_set_time(event_time + (2 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("2 MIN AGO", time_buf); // June 9th 2015, 15:00:00 (T-01:00:00) rtc_set_time(event_time - (1 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 1 H", time_buf); // June 9th 2015, 14:00:00 (T-02:00:00) rtc_set_time(event_time - (2 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 2 H", time_buf); // June 9th 2015, 15:59:00 (T-00:01:00) rtc_set_time(event_time - (1 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 1 MIN", time_buf); // June 9th 2015, 15:58:00 (T-00:02:00) rtc_set_time(event_time - (2 * SECONDS_PER_MINUTE)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("IN 2 MIN", time_buf); // June 10th 2015, 04:00:00 (T+12:00:00) rtc_set_time(event_time + (12 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Yesterday, 16:00", time_buf); // June 9th 2015, 02:00:00 (T-14:00:00) rtc_set_time(event_time - (14 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("16:00", time_buf); // June 8th 2015, 16:00:00 (T-48:00:00) rtc_set_time(event_time - SECONDS_PER_DAY - (24 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Tue, 16:00", time_buf); // June 16th 2015, 17:00:00 (T+7DAY+01:00:00) rtc_set_time(event_time + (7 * SECONDS_PER_DAY) + (1 * SECONDS_PER_HOUR)); clock_get_until_time_capitalized(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Jun 9, 16:00", time_buf); } void test_clock__time_12h_lower_style(void) { char time_buf[64]; const int jun10th_noon_2015 = 1433937600; prv_clock_reset(0); rtc_set_time(jun10th_noon_2015); // Our test event is at June 9th 2015, 16:00:00 // Now - one day const int event_time = jun10th_noon_2015 - SECONDS_PER_DAY + (4 * SECONDS_PER_HOUR); // if the event is within 24 hours, then show the actual time instead of "X hours ago" const int MAX_RELATIVE_HRS = 13; clock_set_24h_style(false); // June 9th 2015, 17:00:00 (T+01:00:00) rtc_set_time(event_time + SECONDS_PER_HOUR); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("An hour ago", time_buf); // June 9th 2015, 17:30:00 (T+01:30:00) rtc_set_time(event_time + SECONDS_PER_HOUR + (30 * SECONDS_PER_MINUTE)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("2 hours ago", time_buf); // June 9th 2015, 16:01:00 (T+00:01:00) rtc_set_time(event_time + (1 * SECONDS_PER_MINUTE)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("1 minute ago", time_buf); // June 9th 2015, 16:02:00 (T+00:02:00) rtc_set_time(event_time + (2 * SECONDS_PER_MINUTE)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("2 minutes ago", time_buf); // June 9th 2015, 15:00:00 (T-01:00:00) rtc_set_time(event_time - (1 * SECONDS_PER_HOUR)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("In 1 hour", time_buf); // June 9th 2015, 14:00:00 (T-02:00:00) rtc_set_time(event_time - (2 * SECONDS_PER_HOUR)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("In 2 hours", time_buf); // June 9th 2015, 15:59:00 (T-00:01:00) rtc_set_time(event_time - (1 * SECONDS_PER_MINUTE)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("In 1 minute", time_buf); // June 9th 2015, 15:58:00 (T-00:02:00) rtc_set_time(event_time - (2 * SECONDS_PER_MINUTE)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("In 2 minutes", time_buf); // June 10th 2015, 04:00:00 (T+12:00:00) rtc_set_time(event_time + (12 * SECONDS_PER_HOUR)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Yesterday, 4:00 PM", time_buf); // June 9th 2015, 02:00:00 (T-14:00:00) rtc_set_time(event_time - (14 * SECONDS_PER_HOUR)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s(" 4:00 PM", time_buf); // June 8th 2015, 16:00:00 (T-48:00:00) rtc_set_time(event_time - SECONDS_PER_DAY - (24 * SECONDS_PER_HOUR)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Tue, 4:00 PM", time_buf); // June 16th 2015, 17:00:00 (T+7DAY+01:00:00) rtc_set_time(event_time + (7 * SECONDS_PER_DAY) + (1 * SECONDS_PER_HOUR)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Jun 9, 4:00 PM", time_buf); } void test_clock__time_24h_lower_style(void) { char time_buf[64]; const int jun10th_noon_2015 = 1433937600; prv_clock_reset(0); rtc_set_time(jun10th_noon_2015); // Our test event is at June 9th 2015, 16:00:00 // Now - one day const int event_time = jun10th_noon_2015 - SECONDS_PER_DAY + (4 * SECONDS_PER_HOUR); // if the event is within 24 hours, then show the actual time instead of "X hours ago" const int MAX_RELATIVE_HRS = 13; clock_set_24h_style(true); // June 9th 2015, 17:00:00 (T+01:00:00) rtc_set_time(event_time + SECONDS_PER_HOUR); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("An hour ago", time_buf); // June 9th 2015, 17:30:00 (T+01:30:00) rtc_set_time(event_time + SECONDS_PER_HOUR + (30 * SECONDS_PER_MINUTE)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("2 hours ago", time_buf); // June 9th 2015, 16:01:00 (T+00:01:00) rtc_set_time(event_time + (1 * SECONDS_PER_MINUTE)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("1 minute ago", time_buf); // June 9th 2015, 16:02:00 (T+00:02:00) rtc_set_time(event_time + (2 * SECONDS_PER_MINUTE)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("2 minutes ago", time_buf); // June 9th 2015, 15:00:00 (T-01:00:00) rtc_set_time(event_time - (1 * SECONDS_PER_HOUR)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("In 1 hour", time_buf); // June 9th 2015, 14:00:00 (T-02:00:00) rtc_set_time(event_time - (2 * SECONDS_PER_HOUR)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("In 2 hours", time_buf); // June 9th 2015, 15:59:00 (T-00:01:00) rtc_set_time(event_time - (1 * SECONDS_PER_MINUTE)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("In 1 minute", time_buf); // June 9th 2015, 15:58:00 (T-00:02:00) rtc_set_time(event_time - (2 * SECONDS_PER_MINUTE)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("In 2 minutes", time_buf); // June 10th 2015, 04:00:00 (T+12:00:00) rtc_set_time(event_time + (12 * SECONDS_PER_HOUR)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Yesterday, 16:00", time_buf); // June 9th 2015, 02:00:00 (T-14:00:00) rtc_set_time(event_time - (14 * SECONDS_PER_HOUR)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("16:00", time_buf); // June 8th 2015, 16:00:00 (T-48:00:00) rtc_set_time(event_time - SECONDS_PER_DAY - (24 * SECONDS_PER_HOUR)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Tue, 16:00", time_buf); // June 16th 2015, 17:00:00 (T+7DAY+01:00:00) rtc_set_time(event_time + (7 * SECONDS_PER_DAY) + (1 * SECONDS_PER_HOUR)); clock_get_until_time(time_buf, sizeof(time_buf), event_time, MAX_RELATIVE_HRS); cl_assert_equal_s("Jun 9, 16:00", time_buf); } void test_clock__month_named_date(void) { char time_buf[64]; const time_t jun10th_noon_2015 = 1433937600; prv_clock_reset(0); rtc_set_time(jun10th_noon_2015); // Our test event is at June 9th 2015, 16:00:00 // Now - one day const time_t event_time = jun10th_noon_2015 - SECONDS_PER_DAY + (4 * SECONDS_PER_HOUR); time_t format_time; clock_set_24h_style(true); // June 9th 2015, 12:00:00 (-07:00:00) format_time = event_time + SECONDS_PER_HOUR; clock_get_month_named_date(time_buf, sizeof(time_buf), format_time); cl_assert_equal_s("June 9", time_buf); // June 10th 2015, 12:00:00 (-07:00:00) format_time = event_time + (24 * SECONDS_PER_HOUR); clock_get_month_named_date(time_buf, sizeof(time_buf), format_time); cl_assert_equal_s("June 10", time_buf); // June 7th 2015, 12:00:00 (-07:00:00) format_time = event_time - SECONDS_PER_DAY - (24 * SECONDS_PER_HOUR); clock_get_month_named_date(time_buf, sizeof(time_buf), format_time); cl_assert_equal_s("June 7", time_buf); // June 16th 2015, 13:00:00 (-07:00:00) format_time = event_time + (7 * SECONDS_PER_DAY) + (1 * SECONDS_PER_HOUR); clock_get_month_named_date(time_buf, sizeof(time_buf), format_time); cl_assert_equal_s("June 16", time_buf); } void test_clock__month_named_abbrev_date(void) { char time_buf[64]; const time_t jun10th_noon_2015 = 1433937600; prv_clock_reset(0); rtc_set_time(jun10th_noon_2015); // Our test event is at June 9th 2015, 16:00:00 // Now - one day const time_t event_time = jun10th_noon_2015 - SECONDS_PER_DAY + (4 * SECONDS_PER_HOUR); time_t format_time; clock_set_24h_style(true); // June 9th 2015, 12:00:00 (-07:00:00) format_time = event_time + SECONDS_PER_HOUR; clock_get_month_named_abbrev_date(time_buf, sizeof(time_buf), format_time); cl_assert_equal_s("Jun 9", time_buf); // June 10th 2015, 12:00:00 (-07:00:00) format_time = event_time + (24 * SECONDS_PER_HOUR); clock_get_month_named_abbrev_date(time_buf, sizeof(time_buf), format_time); cl_assert_equal_s("Jun 10", time_buf); // June 7th 2015, 12:00:00 (-07:00:00) format_time = event_time - SECONDS_PER_DAY - (24 * SECONDS_PER_HOUR); clock_get_month_named_abbrev_date(time_buf, sizeof(time_buf), format_time); cl_assert_equal_s("Jun 7", time_buf); // June 16th 2015, 13:00:00 (-07:00:00) format_time = event_time + (7 * SECONDS_PER_DAY) + (1 * SECONDS_PER_HOUR); clock_get_month_named_abbrev_date(time_buf, sizeof(time_buf), format_time); cl_assert_equal_s("Jun 16", time_buf); } void test_clock__relative_daypart_string(void) { const char *daypart_string = NULL; const char morning[] = "this morning"; // anything before 12pm of the current day const char afternoon[] = "this afternoon"; // 12pm today const char evening[] = "this evening"; // 6pm today const char tonight[] = "tonight"; // 9pm today const char tomorrow_morning[] = "tomorrow morning"; // 9am tomorrow const char tomorrow_afternoon[] = "tomorrow afternoon"; // 12pm tomorrow const char tomorrow_evening[] = "tomorrow evening"; // 6pm tomorrow const char tomorrow_night[] = "tomorrow night"; // 9pm tomorrow // starting 9am 2 days from now and ends midnight 2 days from now const char day_after_tomorrow[] = "the day after tomorrow"; const char future[] = "the foreseeable future"; // Catchall for beyond 3 days // Our test event is at Feb 24 2015, 4:59:00 AM (Day of Second kickstarter) const int feb24_2015 = 1424753940; prv_clock_reset(0); rtc_set_time(feb24_2015); time_t timestamp = rtc_get_time(); // The following are for "Powered 'til" // Which is read as "Powered 'til at least" ... // (4am today) Any time before 12pm is this morning daypart_string = clock_get_relative_daypart_string(timestamp, 0 /* hours_in_the_future */); cl_assert_equal_s(morning, daypart_string); // (8am today) time before 12pm is this morning daypart_string = clock_get_relative_daypart_string(timestamp, 4 /* hours_in_the_future */); cl_assert_equal_s(morning, daypart_string); // (9am today) time before 12pm is this morning daypart_string = clock_get_relative_daypart_string(timestamp, 5 /* hours_in_the_future */); cl_assert_equal_s(morning, daypart_string); // (4pm today) time between 12pm and 6pm is this afternoon daypart_string = clock_get_relative_daypart_string(timestamp, 12 /* hours_in_the_future */); cl_assert_equal_s(afternoon, daypart_string); // (8pm today) time between 6pm and 9pm is this evening daypart_string = clock_get_relative_daypart_string(timestamp, 16 /* hours_in_the_future */); cl_assert_equal_s(evening, daypart_string); // (9pm today) time between 9pm and tomorrow 9am is tonight daypart_string = clock_get_relative_daypart_string(timestamp, 17 /* hours_in_the_future */); cl_assert_equal_s(tonight, daypart_string); // (8am tomorrow) time between 9pm and tomorrow 9am is tonight daypart_string = clock_get_relative_daypart_string(timestamp, 28 /* hours_in_the_future */); cl_assert_equal_s(tonight, daypart_string); // (9am tomorrow) time tomorrow between 9am and 12pm is tomorrow morning daypart_string = clock_get_relative_daypart_string(timestamp, 29 /* hours_in_the_future */); cl_assert_equal_s(tomorrow_morning, daypart_string); // (12pm tomorrow) time tomorrow between 12pm and 6pm is tomorrow afternoon daypart_string = clock_get_relative_daypart_string(timestamp, 32 /* hours_in_the_future */); cl_assert_equal_s(tomorrow_afternoon, daypart_string); // (6pm tomorrow) time tomorrow between 6pm and 9pm is tomorrow evening daypart_string = clock_get_relative_daypart_string(timestamp, 38 /* hours_in_the_future */); cl_assert_equal_s(tomorrow_evening, daypart_string); // (9pm tomorrow) time tomorrow between 9pm and 9am the next day is tomorrow night daypart_string = clock_get_relative_daypart_string(timestamp, 41 /* hours_in_the_future */); cl_assert_equal_s(tomorrow_night, daypart_string); // (9am 2 days from now) time between 9am and 9pm 2 days from now daypart_string = clock_get_relative_daypart_string(timestamp, 53 /* hours_in_the_future */); cl_assert_equal_s(day_after_tomorrow, daypart_string); // (11pm 2 days from now) time between 2 days from now 9am and midnight is the day after tomorrow daypart_string = clock_get_relative_daypart_string(timestamp, 67 /* hours_in_the_future */); cl_assert_equal_s(day_after_tomorrow, daypart_string); // (midnight 2 days from now) time between 2 days from now 9am and midnight // is the day after tomorrow daypart_string = clock_get_relative_daypart_string(timestamp, 68 /* hours_in_the_future */); cl_assert_equal_s(day_after_tomorrow, daypart_string); // (1am 3 days from now) Anything after 2 days from now becomes "the foreseeable future" daypart_string = clock_get_relative_daypart_string(timestamp, 69 /* hours_in_the_future */); cl_assert_equal_s(future, daypart_string); // Our test event is at Oct 31 2015, 22:00:00 const int oct31_2015 = 1446328800; prv_clock_reset(0); rtc_set_time(oct31_2015); timestamp = rtc_get_time(); // (10pm today) time between 9pm and tomorrow 9am is tonight daypart_string = clock_get_relative_daypart_string(timestamp, 0 /* hours_in_the_future */); cl_assert_equal_s(tonight, daypart_string); // (9am tomorrow) time between 9pm and tomorrow 9am is tomorrow morning daypart_string = clock_get_relative_daypart_string(timestamp, 11 /* hours_in_the_future */); cl_assert_equal_s(tomorrow_morning, daypart_string); // Our test event is at Jan 1st 2016, 21:00:00 const int jan1_2016 = 1451682000; prv_clock_reset(0); rtc_set_time(jan1_2016); timestamp = rtc_get_time(); // (9pm today) time between 9pm and tomorrow 9am is tonight daypart_string = clock_get_relative_daypart_string(timestamp, 0 /* hours_in_the_future */); cl_assert_equal_s(tonight, daypart_string); } void test_clock__hour_and_minute_add(void) { int hour = 10; int minute = 15; clock_hour_and_minute_add(&hour, &minute, -30); cl_assert_equal_i(hour, 9); cl_assert_equal_i(minute, 45); hour = 23; minute = 15; clock_hour_and_minute_add(&hour, &minute, 65); cl_assert_equal_i(hour, 0); cl_assert_equal_i(minute, 20); hour = 0; minute = 15; clock_hour_and_minute_add(&hour, &minute, -30); cl_assert_equal_i(hour, 23); cl_assert_equal_i(minute, 45); }