// Copyright (c) 2017-2023, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md
#include <cstring>
#include <iostream>
#include <memory>
#include <unistd.h>
#include <chrono>
#include <regex>
#include "time/time_conversion.hpp"
#include "time/time_locale.hpp"
#include "time/time_conversion_factory.hpp"
#include "mock/TimeSettingsMock.hpp"
#include <catch2/catch.hpp>
using namespace utils::time;
using namespace std::chrono_literals;
class TimeSettings : public TimeSettingsInterface
{
public:
bool timeFormat12h = true;
bool dateFormatDDMM = true;
bool isTimeFormat12h() const final
{
return timeFormat12h;
}
bool isDateFormatDDMM() const final
{
return dateFormatDDMM;
}
};
const std::regex reg12h("^(00|[1-9]|1[0-2]):[0-5][0-9] (A|P)M$");
const std::regex reg12hShort("^(00|[1-9]|1[0-2]):[0-5][0-9]$");
const std::regex reg24h("^(00|[1-9]|1[0-9]|2[0-4]):[0-5][0-9]$");
const std::regex regexDDMMYYYY("^([0-2]\\d|3[0-1])\\.(0[1-9]|1[0-2])\\.\\d{4}$");
const std::regex regexDDMMYY("^([0-2]\\d|3[0-1])\\.(0[1-9]|1[0-2])\\.\\d{2}$");
const std::regex regexDDMM("^([0-2]\\d|3[0-1])\\.(0[1-9]|1[0-2])$");
const std::regex regexMMDDYYYY("^(0[1-9]|1[0-2])\\.([0-2]\\d|3[0-1])\\.\\d{4}$");
const std::regex regexMMDDYY("^(0[1-9]|1[0-2])\\.([0-2]\\d|3[0-1])\\.\\d{2}$");
const std::regex regexMMDD("^(0[1-9]|1[0-2])\\.([0-2]\\d|3[0-1])$");
const std::regex regexDaysOfWeek("^(sun|Sun|mon|Mon|t(ues|hurs)|(T(ues|hurs))|Fri|"
"fri)(day|\\.)?$|wed(\\.|nesday)?$|Wed(\\.|nesday)?$|"
"Sat(\\.|urday)?$|sat(\\.|urday)?$|t((ue?)|(hu?r?))"
"\\.?$|T((ue?)|(hu?r?))\\.?$");
TEST_CASE("TimeStamp")
{
utils::setDisplayLanguage("English");
setenv("TZ", "GMT0", 1);
SECTION("default")
{
Timestamp timestamp;
SECTION("no format specified")
{
REQUIRE(timestamp.str() == "");
}
SECTION("format specified")
{
REQUIRE(timestamp.str("%m.%d.%y %H:%M") == "01.01.70 00:00");
REQUIRE(timestamp.str() == "");
}
SECTION("set format")
{
timestamp.set_format("%m.%d.%Y %H:%M:%S %a %A %b %B %Z");
REQUIRE(timestamp.str() == "01.01.1970 00:00:00 Thu Thursday Jan January GMT");
}
SECTION("set time")
{
timestamp.set_time(1623251054);
REQUIRE(timestamp.str("%m.%d.%y %H:%M:%S") == "06.09.21 15:04:14");
}
SECTION("format too long")
{
REQUIRE(timestamp.str("%m.%d.%Y %H:%M:%S %a %A %b %B %Z %m.%d.%Y %H:%M:%S %a %A %b %B %Z %m.%d.%Y %H:%M:%S "
"%a %A %b %B %Z ") == "");
}
SECTION("timestamp invalid")
{
Timestamp timestamp(static_cast<time_t>(1));
REQUIRE(timestamp.str("%m.%d.%y %H:%M") == "01.01.70 00:00");
}
}
SECTION("timestamp set")
{
// Epoch timestamp: 1623714101
// Timestamp in milliseconds: 1623670901000
// Date and time (GMT): Monday, June 14, 2021 11:41:41 PM
// Date and time (CET): Tuesday, June 15, 2021 1:41:41 AM GMT+02:00
Timestamp timestamp(1623714101);
setenv("TZ", "GMT0", 1);
SECTION("no format specified")
{
REQUIRE(timestamp.str() == "");
}
SECTION("format specified")
{
REQUIRE(timestamp.str("%m.%d.%y %H:%M:%S") == "06.14.21 23:41:41");
REQUIRE(timestamp.str(Locale::format(Locale::TimeFormat::FormatTime12H)) == "11:41 PM");
REQUIRE(timestamp.str(Locale::format(Locale::TimeFormat::FormatTime12HShort)) == "11:41");
REQUIRE(timestamp.str(Locale::format(Locale::TimeFormat::FormatTime24H)) == "23:41");
REQUIRE(timestamp.str(Locale::format(Locale::TimeFormat::FormatLocaleDate_DD_MM_YYYY)) == "14.06.2021");
REQUIRE(timestamp.str(Locale::format(Locale::TimeFormat::FormatLocaleDate_MM_DD_YYYY)) == "06.14.2021");
REQUIRE(timestamp.str(Locale::format(Locale::TimeFormat::FormatLocaleDate_DD_MM_YY)) == "14.06.21");
REQUIRE(timestamp.str(Locale::format(Locale::TimeFormat::FormatLocaleDate_MM_DD_YY)) == "06.14.21");
REQUIRE(timestamp.str(Locale::format(Locale::TimeFormat::FormatLocaleDate_DD_MM)) == "14.06");
REQUIRE(timestamp.str(Locale::format(Locale::TimeFormat::FormatLocaleDate_MM_DD)) == "06.14");
}
SECTION("day and month")
{
// Epoch timestamp: 1609750906
// Timestamp in milliseconds: 1609750906000
// Date and time (GMT): Monday, January 4, 2021 9:01:46 AM
// Date and time (your time zone): Monday, January 4, 2021 10:01:46 AM GMT+01:00
const time_t currentTime = 1609750906;
const auto currentTimeinfo = *std::localtime(¤tTime);
SECTION("day")
{
const std::vector<std::string> days = {
"Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday", "Sunday"};
const std::vector<std::string> daysAbrev = {"Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"};
for (auto i = 0; i < 7; i++) {
auto newTimeinfo = currentTimeinfo;
newTimeinfo.tm_mday += i;
timestamp.set_time(std::mktime(&newTimeinfo));
REQUIRE(timestamp.day(false) == days[i]);
REQUIRE(timestamp.day(true) == daysAbrev[i]);
}
}
SECTION("month")
{
const std::vector<std::string> months = {"January",
"February",
"March",
"April",
"May",
"June",
"July",
"August",
"September",
"October",
"November",
"December"};
const std::vector<std::string> monthsAbrev = {
"Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"};
for (auto i = 0; i < 12; i++) {
auto newTimeinfo = currentTimeinfo;
newTimeinfo.tm_mon += i;
timestamp.set_time(std::mktime(&newTimeinfo));
REQUIRE(timestamp.month(false) == months[i]);
REQUIRE(timestamp.month(true) == monthsAbrev[i]);
}
}
}
SECTION("Timezone change")
{
REQUIRE(timestamp.str("%d.%m.%y %H:%M:%S %Z") == "14.06.21 23:41:41 GMT");
setenv("TZ", "ABC-1", 1);
REQUIRE(timestamp.str("%d.%m.%y %H:%M:%S %Z") == "15.06.21 00:41:41 ABC");
setenv("TZ", "CBA1", 1);
REQUIRE(timestamp.str("%d.%m.%y %H:%M:%S %Z") == "14.06.21 22:41:41 CBA");
}
}
}
TEST_CASE("DateTime formatting")
{
utils::setDisplayLanguage("English");
auto timezone = GENERATE("GMTO", "GMT-2", "GMT+2");
setenv("TZ", timezone, 1);
TimeSettings timeSettings;
const time_t currentTime = GENERATE(1623714101, /* Monday, June 14, 2021 11:41:41 PM GMT */
1625084493, /* Wednesday, June 30, 2021 8:21:33 PM GMT */
1625170893, /* Thursday, July 1, 2021 8:21:33 PM GMT */
1625257293, /* Friday, July 2, 2021 8:21:33 PM GMT */
1640982093, /* Friday, December 31, 2021 8:21:33 PM GMT */
1641068493, /* Saturday, January 1, 2022 8:21:33 PM GMT */
1614525589, /* Sunday, February 28, 2021 3:19:49 PM GMT */
1614611989, /* Monday, March 1, 2021 3:19:49 PM GMT */
1614698389 /* Tuesday, March 2, 2021 3:19:49 PM GMT */
);
const auto currentTimeTimeinfo = *std::localtime(¤tTime);
SECTION("boolean operation 'isToday'")
{
SECTION("test data contained in 'today'")
{
auto newTimeTimeinfo = currentTimeTimeinfo;
auto i = GENERATE(range(0, 23));
newTimeTimeinfo.tm_hour = i;
auto newTime = std::mktime(&newTimeTimeinfo);
DateTime datetime(timeSettings, newTime, currentTime);
REQUIRE(datetime.isToday());
}
SECTION("test data not contained in 'today'")
{
auto newTimeTimeinfo = currentTimeTimeinfo;
SECTION("for a time other than the present day")
{
for (int i = 1; i <= 31; i++) {
newTimeTimeinfo.tm_mday = i;
auto newTime = std::mktime(&newTimeTimeinfo);
if (newTimeTimeinfo.tm_mday == currentTimeTimeinfo.tm_mday) {
continue;
}
DateTime datetime(timeSettings, newTime, currentTime);
REQUIRE(!datetime.isToday());
}
}
SECTION("for a time other than the current month")
{
for (int i = 1; i <= 12; i++) {
newTimeTimeinfo.tm_mon = i;
auto newTime = std::mktime(&newTimeTimeinfo);
if (newTimeTimeinfo.tm_mon == currentTimeTimeinfo.tm_mon) {
continue;
}
DateTime datetime(timeSettings, newTime, currentTime);
REQUIRE(!datetime.isToday());
}
}
SECTION("for the time last year")
{
auto i = GENERATE(range(1, 100));
newTimeTimeinfo.tm_year = currentTimeTimeinfo.tm_year - i;
auto newTime = std::mktime(&newTimeTimeinfo);
DateTime datetime(timeSettings, newTime, currentTime);
REQUIRE(!datetime.isToday());
}
SECTION("for time next year")
{
auto i = GENERATE(range(1, 100));
newTimeTimeinfo.tm_year = currentTimeTimeinfo.tm_year + i;
auto newTime = std::mktime(&newTimeTimeinfo);
DateTime datetime(timeSettings, newTime, currentTime);
REQUIRE(!datetime.isToday());
}
}
}
SECTION("boolean operation 'isYesterday'")
{
auto newTimeTimeinfo = currentTimeTimeinfo;
SECTION("test data contained in 'yesterday'")
{
newTimeTimeinfo.tm_mday -= 1;
for (int i = 0; i < 24; i++) {
newTimeTimeinfo.tm_hour = i;
auto newTime = std::mktime(&newTimeTimeinfo);
DateTime datetime(timeSettings, newTime, currentTime);
REQUIRE(datetime.isYesterday());
}
}
SECTION("test data not contained in 'yesterday'")
{
SECTION("for a day other than 'yesterday'")
{
for (int i = 1; i < 32; i++) {
newTimeTimeinfo.tm_mday = i;
auto newTime = std::mktime(&newTimeTimeinfo);
if (newTimeTimeinfo.tm_mday == currentTimeTimeinfo.tm_mday - 1) {
continue;
}
DateTime datetime(timeSettings, newTime, currentTime);
REQUIRE(!datetime.isYesterday());
}
}
SECTION("for time from different months")
{
for (int i = 0; i < 12; i++) {
newTimeTimeinfo.tm_mon = i;
auto newTime = std::mktime(&newTimeTimeinfo);
DateTime datetime(timeSettings, newTime, currentTime);
REQUIRE(!datetime.isYesterday());
}
}
SECTION("for a time from another year")
{
// previous
for (int i = 1; i < 100; i++) {
newTimeTimeinfo.tm_year = currentTimeTimeinfo.tm_year - i;
auto newTime = std::mktime(&newTimeTimeinfo);
DateTime datetime(timeSettings, newTime, currentTime);
REQUIRE(!datetime.isYesterday());
}
// forward
for (int i = 1; i < 100; i++) {
newTimeTimeinfo.tm_year = currentTimeTimeinfo.tm_year + i;
auto newTime = std::mktime(&newTimeTimeinfo);
DateTime datetime(timeSettings, newTime, currentTime);
REQUIRE(!datetime.isYesterday());
}
}
}
}
SECTION("boolean operation 'isCurrentYear'")
{
auto newTimeTimeinfo = currentTimeTimeinfo;
SECTION("for time from different days")
{
for (int i = 1; i < 32; i++) {
newTimeTimeinfo.tm_mday = i;
auto newTime = std::mktime(&newTimeTimeinfo);
DateTime datetime(timeSettings, newTime, currentTime);
REQUIRE(datetime.isCurrentYear());
}
}
SECTION("for time from different months")
{
for (int i = 0; i < 12; i++) {
newTimeTimeinfo.tm_mon = i;
auto newTime = std::mktime(&newTimeTimeinfo);
DateTime datetime(timeSettings, newTime, currentTime);
REQUIRE(datetime.isCurrentYear());
}
}
SECTION("for time from different years")
{
// previous
for (int i = 1; i < 100; i++) {
newTimeTimeinfo.tm_year = currentTimeTimeinfo.tm_year - i;
auto newTime = std::mktime(&newTimeTimeinfo);
DateTime datetime(timeSettings, newTime, currentTime);
REQUIRE(!datetime.isCurrentYear());
}
// forward
for (int i = 1; i < 100; i++) {
newTimeTimeinfo.tm_year = currentTimeTimeinfo.tm_year + i;
auto newTime = std::mktime(&newTimeTimeinfo);
DateTime datetime(timeSettings, newTime, currentTime);
REQUIRE(!datetime.isCurrentYear());
}
}
}
SECTION("boolean operation 'isCurrentWeek'")
{
auto newTimeTimeinfo = currentTimeTimeinfo;
SECTION("test data contained in 'current week'")
{
auto i = GENERATE(range(2, 7));
newTimeTimeinfo.tm_mday -= i;
const auto newTime = std::mktime(&newTimeTimeinfo);
DateTime datetime(timeSettings, newTime, currentTime);
REQUIRE(datetime.isCurrentWeek());
}
SECTION("test data not contained in 'current week'")
{
auto newTimeTimeinfo = currentTimeTimeinfo;
SECTION("for days other than the last week")
{
auto i = GENERATE(range(7, 32));
newTimeTimeinfo.tm_mday -= i;
auto newTime = std::mktime(&newTimeTimeinfo);
DateTime datetime(timeSettings, newTime, currentTime);
REQUIRE(!datetime.isCurrentWeek());
}
SECTION("for time from different months")
{
auto i = GENERATE(range(1, 12));
newTimeTimeinfo.tm_mon -= i;
auto newTime = std::mktime(&newTimeTimeinfo);
DateTime datetime(timeSettings, newTime, currentTime);
REQUIRE(!datetime.isCurrentWeek());
}
SECTION("for earlier years")
{
auto i = GENERATE(range(1, 10));
newTimeTimeinfo.tm_year = currentTimeTimeinfo.tm_year - i;
auto newTime = std::mktime(&newTimeTimeinfo);
DateTime datetime(timeSettings, newTime, currentTime);
REQUIRE(!datetime.isCurrentWeek());
}
SECTION("for the time in the following years")
{
auto i = GENERATE(range(1, 10));
newTimeTimeinfo.tm_year = currentTimeTimeinfo.tm_year + i;
auto newTime = std::mktime(&newTimeTimeinfo);
DateTime datetime(timeSettings, newTime, currentTime);
REQUIRE(!datetime.isCurrentWeek());
}
}
}
SECTION("Date/time displayed")
{
auto newTimeTimeinfo = currentTimeTimeinfo;
timeSettings.timeFormat12h = true;
timeSettings.dateFormatDDMM = true;
SECTION("Date or time formatting depending on the reference time difference")
{
SECTION("for the current time")
{
std::regex reg = reg12h;
auto newTime = std::mktime(&newTimeTimeinfo);
DateOrTime datetime(timeSettings, newTime, currentTime);
REQUIRE(std::regex_match(std::string(datetime.str()), reg));
timeSettings.timeFormat12h = false;
reg = reg24h;
REQUIRE(std::regex_match(std::string(datetime.str()), reg));
}
SECTION("for the time yesterday")
{
newTimeTimeinfo.tm_mday -= 1;
auto newTime = std::mktime(&newTimeTimeinfo);
DateOrTime datetime(timeSettings, newTime, currentTime);
REQUIRE(datetime.str() == "Yesterday");
}
SECTION("for a time earlier than yesterday but still in the same week")
{
newTimeTimeinfo.tm_mday -= 6;
const auto newTime = std::mktime(&newTimeTimeinfo);
DateOrTime datetime(timeSettings, newTime, currentTime);
REQUIRE(std::regex_match(std::string(datetime.str()), regexDaysOfWeek));
}
SECTION("for a time earlier than a week but still in the same year")
{
std::regex regexSameYear = regexDDMM;
if (newTimeTimeinfo.tm_mon == 0) {
newTimeTimeinfo.tm_mon = 1;
}
else {
newTimeTimeinfo.tm_mon -= 1;
}
auto newTime = std::mktime(&newTimeTimeinfo);
DateOrTime datetime(timeSettings, newTime, currentTime);
REQUIRE(std::regex_match(std::string(datetime.str()), regexSameYear));
timeSettings.dateFormatDDMM = false;
regexSameYear = regexMMDD;
REQUIRE(std::regex_match(std::string(datetime.str()), regexSameYear));
}
SECTION("for the time last year")
{
std::regex regexPreviousYear = regexDDMMYYYY;
newTimeTimeinfo.tm_year -= 1;
auto newTime = std::mktime(&newTimeTimeinfo);
DateOrTime datetime(timeSettings, newTime, currentTime);
REQUIRE(std::regex_match(std::string(datetime.str()), regexPreviousYear));
timeSettings.dateFormatDDMM = false;
regexPreviousYear = regexMMDDYYYY;
REQUIRE(std::regex_match(std::string(datetime.str()), regexPreviousYear));
}
}
SECTION("Date and time formatting")
{
SECTION("for the current time")
{
std::regex reg = reg12h;
auto newTime = std::mktime(&newTimeTimeinfo);
DateAndTime datetime(timeSettings, newTime, currentTime);
REQUIRE(std::regex_match(std::string(datetime.str()), reg));
timeSettings.timeFormat12h = false;
reg = reg24h;
REQUIRE(std::regex_match(std::string(datetime.str()), reg));
}
SECTION("for the time yesterday")
{
newTimeTimeinfo.tm_mday -= 1;
auto newTime = std::mktime(&newTimeTimeinfo);
DateAndTime datetime(timeSettings, newTime, currentTime);
const std::string dateTimeStr = datetime.str();
const int pos = dateTimeStr.find_first_of('\n');
const std::string timeStr = dateTimeStr.substr(pos + 1), dateStr = dateTimeStr.substr(0, pos);
REQUIRE(dateStr == "Yesterday");
REQUIRE(std::regex_match(timeStr, reg12h));
}
SECTION("for a time earlier than yesterday but still in the same week")
{
newTimeTimeinfo.tm_mday -= 6;
const auto newTime = std::mktime(&newTimeTimeinfo);
DateAndTime datetime(timeSettings, newTime, currentTime);
const std::string dateTimeStr = datetime.str();
const int pos = dateTimeStr.find_first_of('\n');
const std::string timeStr = dateTimeStr.substr(pos + 1), dateStr = dateTimeStr.substr(0, pos);
REQUIRE(std::regex_match(dateStr, regexDaysOfWeek));
REQUIRE(std::regex_match(timeStr, reg12h));
}
SECTION("for a time earlier than a week but still in the same year")
{
std::regex regexSameYear = regexDDMM;
if (newTimeTimeinfo.tm_mon == 0) {
newTimeTimeinfo.tm_mon = 1;
}
else {
newTimeTimeinfo.tm_mon -= 1;
}
auto newTime = std::mktime(&newTimeTimeinfo);
DateAndTime datetime(timeSettings, newTime, currentTime);
std::string dateTimeStr = datetime.str();
int pos = dateTimeStr.find_first_of('\n');
std::string timeStr = dateTimeStr.substr(pos + 1), dateStr = dateTimeStr.substr(0, pos);
REQUIRE(std::regex_match(dateStr, regexSameYear));
REQUIRE(std::regex_match(timeStr, reg12h));
timeSettings.dateFormatDDMM = false;
regexSameYear = regexMMDD;
dateTimeStr = datetime.str();
pos = dateTimeStr.find_first_of('\n');
timeStr = dateTimeStr.substr(pos + 1);
dateStr = dateTimeStr.substr(0, pos);
REQUIRE(std::regex_match(dateStr, regexSameYear));
REQUIRE(std::regex_match(timeStr, reg12h));
}
SECTION("for the time last year")
{
std::regex regexPreviousYear = regexDDMMYY;
newTimeTimeinfo.tm_year -= 1;
auto newTime = std::mktime(&newTimeTimeinfo);
DateAndTime datetime(timeSettings, newTime, currentTime);
std::string dateTimeStr = datetime.str();
int pos = dateTimeStr.find_first_of('\n');
std::string timeStr = dateTimeStr.substr(pos + 1), dateStr = dateTimeStr.substr(0, pos);
REQUIRE(std::regex_match(dateStr, regexPreviousYear));
REQUIRE(std::regex_match(timeStr, reg12h));
timeSettings.dateFormatDDMM = false;
regexPreviousYear = regexMMDDYY;
dateTimeStr = datetime.str();
pos = dateTimeStr.find_first_of('\n');
timeStr = dateTimeStr.substr(pos + 1);
dateStr = dateTimeStr.substr(0, pos);
REQUIRE(std::regex_match(dateStr, regexPreviousYear));
REQUIRE(std::regex_match(timeStr, reg12h));
}
}
}
}
TEST_CASE("Time")
{
utils::setDisplayLanguage("English");
setenv("TZ", "GMT0", 1);
TimeSettings timeSettings;
SECTION("Display")
{
const auto currentTime = 1623714101; // Monday, June 14, 2021 11:41:41 PM GMT
timeSettings.timeFormat12h = true;
timeSettings.dateFormatDDMM = true;
SECTION("now")
{
std::regex reg = reg12h;
Time time(timeSettings, currentTime);
REQUIRE(std::regex_match(std::string(time.str()), reg));
timeSettings.timeFormat12h = false;
reg = reg24h;
REQUIRE(std::regex_match(std::string(time.str()), reg));
}
}
}
TEST_CASE("Clock")
{
utils::setDisplayLanguage("English");
setenv("TZ", "GMT0", 1);
TimeSettings timeSettings;
SECTION("Display")
{
const auto currentTime = 1623714101; // Monday, June 14, 2021 11:41:41 PM GMT
timeSettings.timeFormat12h = true;
timeSettings.dateFormatDDMM = true;
SECTION("now")
{
std::regex reg = reg12hShort;
Clock clock(timeSettings, currentTime);
REQUIRE(std::regex_match(std::string(clock.str()), reg));
timeSettings.timeFormat12h = false;
reg = reg24h;
REQUIRE(std::regex_match(std::string(clock.str()), reg));
}
}
}
TEST_CASE("Date")
{
utils::setDisplayLanguage("English");
setenv("TZ", "GMT0", 1);
TimeSettings timeSettings;
SECTION("Display")
{
const auto currentTime = 1623714101; // Monday, June 14, 2021 11:41:41 PM GMT
timeSettings.timeFormat12h = true;
timeSettings.dateFormatDDMM = true;
SECTION("now")
{
std::regex reg = regexDDMMYYYY;
Date date(timeSettings, currentTime);
REQUIRE(std::regex_match(std::string(date.str()), reg));
timeSettings.dateFormatDDMM = false;
reg = regexMMDDYYYY;
REQUIRE(std::regex_match(std::string(date.str()), reg));
}
}
}
TEST_CASE("DateText")
{
utils::setDisplayLanguage("English");
setenv("TZ", "GMT0", 1);
TimeSettings timeSettings;
SECTION("Display")
{
// Epoch timestamp: 1623714101
// Timestamp in milliseconds: 1623670901000
// Date and time (GMT): Monday, June 14, 2021 11:41:41 PM
// Date and time (CET): Tuesday, June 15, 2021 1:41:41 AM GMT+02:00
DateText timestamp(timeSettings, 1623714101);
setenv("TZ", "GMT0", 1);
timeSettings.timeFormat12h = true;
timeSettings.dateFormatDDMM = true;
SECTION("now")
{
REQUIRE(timestamp.str() == "Monday, 14 Jun");
timeSettings.dateFormatDDMM = false;
REQUIRE(timestamp.str() == "Monday, Jun 14");
}
}
}
TEST_CASE("Duration - creation")
{
utils::setDisplayLanguage("English");
SECTION("default constructor")
{
utils::time::Duration duration;
REQUIRE(duration.get() == 0);
}
SECTION("time_t constructor")
{
utils::time::Duration duration(333);
REQUIRE(duration.get() == 333);
}
SECTION("std::chrono::seconds constructor")
{
utils::time::Duration duration(std::chrono::seconds(333));
REQUIRE(duration.get() == 333);
}
SECTION("std::chrono::seconds by minutes constructor")
{
auto minutes = std::chrono::minutes(2);
utils::time::Duration duration(minutes);
REQUIRE(duration.get() == 120);
}
SECTION("stop < start time_t constructor")
{
utils::time::Duration duration(100, 202);
REQUIRE(duration.get() == 0);
}
SECTION("stop > start time_t constructor")
{
utils::time::Duration duration(202, 102);
REQUIRE(duration.get() == 100);
}
SECTION("Start and Stop Timestamp constructor")
{
utils::time::Timestamp tstart(100);
utils::time::Timestamp tstop(202);
{
utils::time::Duration duration(tstop, tstart);
REQUIRE(duration.get() == 102);
}
{
utils::time::Duration duration(tstart, tstop);
REQUIRE(duration.get() == 0);
}
}
}
TEST_CASE("Duration - arithemtics")
{
utils::setDisplayLanguage("English");
SECTION("Addition")
{
utils::time::Duration d1(100), d2(200);
utils::time::Timestamp t1(100);
auto t2 = t1 + d1;
REQUIRE(t2.getTime() == 200);
auto t3 = d1 + t1;
REQUIRE(t3.getTime() == 200);
auto d3 = d1 + d2;
REQUIRE(d3.get() == 300);
auto d4 = d1 + utils::time::Duration(5);
REQUIRE(d4.get() == 105);
}
SECTION("Substraction")
{
utils::time::Duration d1(1000);
utils::time::Timestamp t1(100), t2(205);
auto d2 = t1 - t2;
REQUIRE(d2.get() == 0);
auto d3 = t2 - t1;
REQUIRE(d3.get() == 105);
auto d4 = d1 - d3;
REQUIRE(d4.get() == 895);
auto d5 = d3 - d1;
REQUIRE(d5.get() == 0);
}
}
TEST_CASE("Duration - comparision")
{
utils::setDisplayLanguage("English");
SECTION("Duration")
{
utils::time::Duration d1(100), d2(200), d3(200);
REQUIRE(!(d1 == d3));
REQUIRE(d2 == d3);
REQUIRE(d1 != d3);
REQUIRE(!(d2 != d3));
REQUIRE(d1 < d2);
REQUIRE(!(d2 < d3));
REQUIRE(d2 > d1);
REQUIRE(!(d2 > d3));
REQUIRE(d1 <= d2);
REQUIRE(d2 <= d3);
REQUIRE(d2 >= d1);
REQUIRE(d2 >= d3);
}
SECTION("Timestamps")
{
utils::time::Timestamp t1(100), t2(200), t3(200);
REQUIRE(!(t1 == t3));
REQUIRE(t2 == t3);
REQUIRE(t1 != t3);
REQUIRE(!(t2 != t3));
REQUIRE(t1 < t2);
REQUIRE(!(t2 < t3));
REQUIRE(t2 > t1);
REQUIRE(!(t2 > t3));
REQUIRE(t1 <= t2);
REQUIRE(t2 <= t3);
REQUIRE(t2 >= t1);
REQUIRE(t2 >= t3);
}
}
TEST_CASE("Duration - display")
{
utils::setDisplayLanguage("English");
{
using namespace utils::time;
Duration duration;
REQUIRE(duration.get() == 0);
duration = 0;
REQUIRE(duration.str(Duration::DisplayedFormat::Auto0M) == "00:00");
REQUIRE(duration.str(Duration::DisplayedFormat::AutoM) == "0:00");
REQUIRE(duration.str(Duration::DisplayedFormat::Fixed0M0S) == "00:00");
REQUIRE(duration.str(Duration::DisplayedFormat::FixedH0M0S) == "0:00:00");
duration = 8;
REQUIRE(duration.str(Duration::DisplayedFormat::Auto0M) == "00:08");
REQUIRE(duration.str(Duration::DisplayedFormat::AutoM) == "0:08");
REQUIRE(duration.str(Duration::DisplayedFormat::Fixed0M0S) == "00:08");
REQUIRE(duration.str(Duration::DisplayedFormat::FixedH0M0S) == "0:00:08");
duration = 20;
REQUIRE(duration.str(Duration::DisplayedFormat::Auto0M) == "00:20");
REQUIRE(duration.str(Duration::DisplayedFormat::AutoM) == "0:20");
REQUIRE(duration.str(Duration::DisplayedFormat::Fixed0M0S) == "00:20");
REQUIRE(duration.str(Duration::DisplayedFormat::FixedH0M0S) == "0:00:20");
duration = 1 * 60 + 59;
REQUIRE(duration.str(Duration::DisplayedFormat::Auto0M) == "01:59");
REQUIRE(duration.str(Duration::DisplayedFormat::AutoM) == "1:59");
REQUIRE(duration.str(Duration::DisplayedFormat::Fixed0M0S) == "01:59");
REQUIRE(duration.str(Duration::DisplayedFormat::FixedH0M0S) == "0:01:59");
duration = 2 * 60 + 30;
REQUIRE(duration.str(Duration::DisplayedFormat::Auto0M) == "02:30");
REQUIRE(duration.str(Duration::DisplayedFormat::AutoM) == "2:30");
REQUIRE(duration.str(Duration::DisplayedFormat::Fixed0M0S) == "02:30");
REQUIRE(duration.str(Duration::DisplayedFormat::FixedH0M0S) == "0:02:30");
duration = 19 * 60 + 32;
REQUIRE(duration.str(Duration::DisplayedFormat::Auto0M) == "19:32");
REQUIRE(duration.str(Duration::DisplayedFormat::AutoM) == "19:32");
REQUIRE(duration.str(Duration::DisplayedFormat::Fixed0M0S) == "19:32");
REQUIRE(duration.str(Duration::DisplayedFormat::FixedH0M0S) == "0:19:32");
duration = 1 * 60 * 60 + 6 * 60 + 9;
REQUIRE(duration.str(Duration::DisplayedFormat::Auto0M) == "1:06:09");
REQUIRE(duration.str(Duration::DisplayedFormat::AutoM) == "1:06:09");
REQUIRE(duration.str(Duration::DisplayedFormat::Fixed0M0S) == "66:09");
REQUIRE(duration.str(Duration::DisplayedFormat::FixedH0M0S) == "1:06:09");
duration = 1 * 60 * 60 + 29 * 60 + 32;
REQUIRE(duration.str(Duration::DisplayedFormat::Auto0M) == "1:29:32");
REQUIRE(duration.str(Duration::DisplayedFormat::AutoM) == "1:29:32");
REQUIRE(duration.str(Duration::DisplayedFormat::Fixed0M0S) == "89:32");
REQUIRE(duration.str(Duration::DisplayedFormat::FixedH0M0S) == "1:29:32");
duration = 27 * 60 * 60 + 23 * 60 + 14;
REQUIRE(duration.str(Duration::DisplayedFormat::Auto0M) == "27:23:14");
REQUIRE(duration.str(Duration::DisplayedFormat::AutoM) == "27:23:14");
REQUIRE(duration.str(Duration::DisplayedFormat::Fixed0M0S) == "1643:14");
REQUIRE(duration.str(Duration::DisplayedFormat::FixedH0M0S) == "27:23:14");
duration = 48 * 60 * 60 + 3 * 60 + 4;
REQUIRE(duration.str(Duration::DisplayedFormat::Auto0M) == "48:03:04");
REQUIRE(duration.str(Duration::DisplayedFormat::AutoM) == "48:03:04");
REQUIRE(duration.str(Duration::DisplayedFormat::Fixed0M0S) == "2883:04");
REQUIRE(duration.str(Duration::DisplayedFormat::FixedH0M0S) == "48:03:04");
}
}
TEST_CASE("Timestamp factory")
{
SECTION("No setting provided")
{
auto timestamp = utils::time::TimestampFactory().createTimestamp(utils::time::TimestampType::Clock);
REQUIRE(typeid(*(timestamp.get())).name() == typeid(utils::time::Timestamp).name());
}
SECTION("Settings provided")
{
auto factory = utils::time::TimestampFactory();
factory.init(new BaseTimeSettings);
auto timestamp = factory.createTimestamp(utils::time::TimestampType::Clock);
REQUIRE(typeid(*(timestamp.get())).name() == typeid(utils::time::Clock).name());
}
}