~aleteoryx/muditaos

ccc49c7b9c2ecf69e26b099d71c2bab0e9914359 — KacperLewandowski 5 years ago 3178bc7
[EGD-3698] Add UT for TimeRangeParser. (#750)

Move TimeRangeParser to module-utils.
M changelog.md => changelog.md +4 -0
@@ 14,6 14,10 @@

* `[alarms]` Database refactor

### Other

* `[utils]` Added unit tests for time display.

## [0.48.1 2020-11-23]

### Added

M module-apps/application-calendar/CMakeLists.txt => module-apps/application-calendar/CMakeLists.txt +0 -1
@@ 38,7 38,6 @@
		"${CMAKE_CURRENT_LIST_DIR}/widgets/CalendarStyle.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/data/OptionParser.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/data/CalendarData.hpp"
		"${CMAKE_CURRENT_LIST_DIR}/data/TimeDisplayParser.hpp"
)

target_link_libraries(${PROJECT_NAME}

D module-apps/application-calendar/data/TimeDisplayParser.hpp => module-apps/application-calendar/data/TimeDisplayParser.hpp +0 -102
@@ 1,102 0,0 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once
#include "module-apps/application-calendar/widgets/CalendarStyle.hpp"
#include <Utils.hpp>
#include <module-db/Interface/EventsRecord.hpp>
#include <time/time_locale.hpp>

class TimeDisplayParser
{

  private:
    std::string getAMorPM(bool is_am)
    {
        if (is_am) {
            return utils::localize.get(utils::time::Locale::getAM());
        }
        else {
            return utils::localize.get(utils::time::Locale::getPM());
        }
    }

  public:
    TimeDisplayParser() = default;

    std::string getTimeString(const std::shared_ptr<EventsRecord> &event,
                              bool isShortVersion = false,
                              bool isMode24H      = false)
    {
        auto start_time = TimePointToHourMinSec(event->date_from);
        auto end_time   = TimePointToHourMinSec(event->date_till);

        if (start_time.hours().count() == 0 && start_time.minutes().count() == 0 &&
            end_time.hours().count() == style::window::calendar::time::max_hour_24H_mode &&
            end_time.minutes().count() == style::window::calendar::time::max_minutes) {
            return utils::localize.get("app_calendar_all_day");
        }
        else {
            bool start_is_am = true;
            bool end_is_am   = true;
            auto start_h     = std::to_string(start_time.hours().count());
            auto start_min   = std::to_string(start_time.minutes().count());
            auto end_h       = std::to_string(end_time.hours().count());
            auto end_min     = std::to_string(end_time.minutes().count());

            if (start_min.length() < style::window::calendar::time::max_time_length) {
                start_min.insert(0, style::window::calendar::time::max_time_length / 2, '0');
            }
            if (end_min.length() < style::window::calendar::time::max_time_length) {
                end_min.insert(0, style::window::calendar::time::max_time_length / 2, '0');
            }

            if (!isMode24H) {
                start_is_am = date::is_am(start_time.hours());
                end_is_am   = date::is_am(end_time.hours());
                start_h     = std::to_string(date::make12(start_time.hours()).count());
                end_h       = std::to_string(date::make12(end_time.hours()).count());
            }

            if (start_h.length() < style::window::calendar::time::max_time_length) {
                start_h.insert(0, style::window::calendar::time::max_time_length / 2, '0');
            }
            if (end_h.length() < style::window::calendar::time::max_time_length) {
                end_h.insert(0, style::window::calendar::time::max_time_length / 2, '0');
            }

            if (isShortVersion) {
                if (!isMode24H) {
                    return TimePointToHourString12H(event->date_from) + ":" +
                           TimePointToMinutesString(event->date_from) + " " + getAMorPM(start_is_am);
                }
                else {
                    return TimePointToHourString24H(event->date_from) + ":" +
                           TimePointToMinutesString(event->date_from);
                }
            }
            else {
                if (!isMode24H) {
                    if (start_is_am != end_is_am) {
                        return TimePointToHourString12H(event->date_from) + ":" +
                               TimePointToMinutesString(event->date_from) + " " + getAMorPM(start_is_am) + " - " +
                               TimePointToHourString12H(event->date_till) + ":" +
                               TimePointToMinutesString(event->date_till) + " " + getAMorPM(end_is_am);
                    }
                    else {
                        return TimePointToHourString12H(event->date_from) + ":" +
                               TimePointToMinutesString(event->date_from) + " - " +
                               TimePointToHourString12H(event->date_till) + ":" +
                               TimePointToMinutesString(event->date_till) + " " + getAMorPM(start_is_am);
                    }
                }
                else {
                    return TimePointToHourString24H(event->date_from) + ":" +
                           TimePointToMinutesString(event->date_from) + " - " +
                           TimePointToMinutesString(event->date_till) + ":" +
                           TimePointToMinutesString(event->date_till);
                }
            }
        }
    }
};

M module-apps/application-calendar/data/dateCommon.hpp => module-apps/application-calendar/data/dateCommon.hpp +8 -6
@@ 6,6 6,7 @@

#include <module-utils/date/include/date/date.h>
#include <time/time_conversion.hpp>
#include <Utils.hpp>
#include <random>

using namespace std::chrono;


@@ 227,16 228,17 @@ inline uint32_t TimePointToHour12H(const TimePoint &tp)

inline std::string TimePointToHourString12H(const TimePoint &tp)
{
    auto hour       = TimePointToHour12H(tp);
    auto hourString = std::to_string(hour);
    return hourString;
    auto hour =
        utils::time::Timestamp(TimePointToTimeT(tp)).get_UTC_date_time_sub_value(utils::time::GetParameters::Hour);
    auto hour12h = date::make12(std::chrono::hours(hour)).count();
    return utils::to_string(hour12h);
}

inline std::string TimePointToHourString24H(const TimePoint &tp)
{
    auto hour       = TimePointToHour24H(tp);
    auto hourString = std::to_string(hour);
    return hourString;
    auto hour =
        utils::time::Timestamp(TimePointToTimeT(tp)).get_UTC_date_time_sub_value(utils::time::GetParameters::Hour);
    return utils::to_string(hour);
}

inline std::string TimePointToMinutesString(const TimePoint &tp)

M module-apps/application-calendar/widgets/AllEventsItem.cpp => module-apps/application-calendar/widgets/AllEventsItem.cpp +3 -3
@@ 3,12 3,11 @@

#include "AllEventsItem.hpp"
#include "application-calendar/widgets/CalendarStyle.hpp"
#include "application-calendar/data/TimeDisplayParser.hpp"
#include "CalendarListItem.hpp"
#include <Style.hpp>
#include <gui/widgets/Label.hpp>
#include <time/time_conversion.hpp>
#include <module-utils/date/include/date/date.h>
#include <module-utils/time/TimeRangeParser.hpp>

namespace gui
{


@@ 82,7 81,8 @@ namespace gui
        this->record = rec;
        if (rec != nullptr) {
            description->setText(this->record->title.c_str());
            startTime->setText(TimeDisplayParser().getTimeString(record, true));
            startTime->setText(utils::time::TimeRangeParser().getCalendarTimeString(
                record->date_from, record->date_till, utils::time::Version::abbrev));
        }
    }
} /* namespace gui */

M module-apps/application-calendar/widgets/DayEventsItem.cpp => module-apps/application-calendar/widgets/DayEventsItem.cpp +2 -2
@@ 3,10 3,10 @@

#include "DayEventsItem.hpp"
#include "CalendarStyle.hpp"
#include "application-calendar/data/TimeDisplayParser.hpp"
#include <ListView.hpp>
#include <gui/widgets/Label.hpp>
#include <Style.hpp>
#include <module-utils/time/TimeRangeParser.hpp>

namespace gui
{


@@ 49,7 49,7 @@ namespace gui

        if (rec != nullptr) {
            description->setText(this->record->title.c_str());
            title->setText(TimeDisplayParser().getTimeString(record));
            title->setText(utils::time::TimeRangeParser().getCalendarTimeString(record->date_from, record->date_till));
            if (record->reminder == static_cast<uint32_t>(Reminder::never)) {
                clock->setVisible(false);
            }

M module-apps/application-calendar/widgets/EventDetailDescriptionItem.cpp => module-apps/application-calendar/widgets/EventDetailDescriptionItem.cpp +3 -2
@@ 3,10 3,10 @@

#include "EventDetailDescriptionItem.hpp"
#include "application-calendar/widgets/CalendarStyle.hpp"
#include "application-calendar/data/TimeDisplayParser.hpp"
#include <Style.hpp>
#include <time/time_conversion.hpp>
#include <module-utils/date/include/date/date.h>
#include <module-utils/time/TimeRangeParser.hpp>

namespace gui
{


@@ 79,7 79,8 @@ namespace gui
        title->setText(utils::localize.get("app_calendar_event_detail"));
        onLoadCallback = [&](std::shared_ptr<EventsRecord> event) {
            description->setText(event->title);
            eventTime->setText(TimeDisplayParser().getTimeString(event));
            eventTime->setText(
                utils::time::TimeRangeParser().getCalendarTimeString(event->date_from, event->date_till));
        };
    }


M module-utils/CMakeLists.txt => module-utils/CMakeLists.txt +1 -0
@@ 34,6 34,7 @@ set (SOURCES
        ${CMAKE_CURRENT_SOURCE_DIR}/country.hpp
        ${CMAKE_CURRENT_SOURCE_DIR}/state/ServiceState.hpp
        ${CMAKE_CURRENT_SOURCE_DIR}/ical/ParserICS.cpp
		${CMAKE_CURRENT_SOURCE_DIR}/time/TimeRangeParser.cpp
)

add_library(${PROJECT_NAME} STATIC ${SOURCES} ${BOARD_SOURCES})

M module-utils/test/CMakeLists.txt => module-utils/test/CMakeLists.txt +11 -0
@@ 85,6 85,17 @@ add_catch2_executable(
#        module-utils
#)

#  time display tests
#add_catch2_executable(
#    NAME
#        utils-time_display
#    SRCS
#        unittest_TimeRangeParser.cpp
#    LIBS
#        module-utils
#        module-db
#)

###########################################
# Log functional tests project
project(test_module-utils_log VERSION 1.0

A module-utils/test/unittest_TimeRangeParser.cpp => module-utils/test/unittest_TimeRangeParser.cpp +143 -0
@@ 0,0 1,143 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#define CATCH_CONFIG_MAIN
#include <catch2/catch.hpp>
#include "time/TimeRangeParser.hpp"
#include <module-apps/application-calendar/data/dateCommon.hpp>
#include <module-db/Interface/EventsRecord.hpp>

#include <cstdint>
#include <cstring>
#include <iostream>

TEST_CASE("Time display parser")
{
    using utils::time::Version;
    SECTION("After noon time input (mode12h)")
    {
        auto event      = EventsRecord();
        event.date_from = TimePointFromString("2020-10-10 14:24:00");
        event.date_till = TimePointFromString("2020-10-10 15:36:00");

        auto returnString = utils::time::TimeRangeParser().getCalendarTimeString(
            event.date_from, event.date_till, Version::normal, false);
        REQUIRE("2020-10-10 14:24:00" == TimePointToString(event.date_from));
        REQUIRE("2020-10-10 15:36:00" == TimePointToString(event.date_till));
        REQUIRE("2" == TimePointToHourString12H(event.date_from));
        REQUIRE("24" == TimePointToMinutesString(event.date_from));
        REQUIRE("3" == TimePointToHourString12H(event.date_till));
        REQUIRE("36" == TimePointToMinutesString(event.date_till));
        REQUIRE(returnString == "2:24 - 3:36 " + utils::localize.get(utils::time::Locale::getPM()));
    }

    SECTION("Before noon time input (mode12h)")
    {
        auto event      = EventsRecord();
        event.date_from = TimePointFromString("2020-12-31 05:59:00");
        event.date_till = TimePointFromString("2020-12-31 07:45:00");

        auto returnString = utils::time::TimeRangeParser().getCalendarTimeString(
            event.date_from, event.date_till, Version::normal, false);
        REQUIRE("2020-12-31 05:59:00" == TimePointToString(event.date_from));
        REQUIRE("2020-12-31 07:45:00" == TimePointToString(event.date_till));
        REQUIRE("5" == TimePointToHourString12H(event.date_from));
        REQUIRE("59" == TimePointToMinutesString(event.date_from));
        REQUIRE("7" == TimePointToHourString12H(event.date_till));
        REQUIRE("45" == TimePointToMinutesString(event.date_till));
        REQUIRE(returnString == "5:59 - 7:45 " + utils::localize.get(utils::time::Locale::getAM()));
    }

    SECTION("Mixed time input (mode12h)")
    {
        auto event      = EventsRecord();
        event.date_from = TimePointFromString("2021-01-01 01:05:00");
        event.date_till = TimePointFromString("2021-01-01 19:55:00");

        auto returnString = utils::time::TimeRangeParser().getCalendarTimeString(
            event.date_from, event.date_till, Version::normal, false);
        REQUIRE("2021-01-01 01:05:00" == TimePointToString(event.date_from));
        REQUIRE("2021-01-01 19:55:00" == TimePointToString(event.date_till));
        REQUIRE("1" == TimePointToHourString12H(event.date_from));
        REQUIRE("05" == TimePointToMinutesString(event.date_from));
        REQUIRE("7" == TimePointToHourString12H(event.date_till));
        REQUIRE("55" == TimePointToMinutesString(event.date_till));
        REQUIRE(returnString == "1:05 " + utils::localize.get(utils::time::Locale::getAM()) + " - 7:55 " +
                                    utils::localize.get(utils::time::Locale::getPM()));
    }

    SECTION("Before noon time input - short version (mode12h)")
    {
        auto event      = EventsRecord();
        event.date_from = TimePointFromString("2020-12-31 00:05:00");
        event.date_till = TimePointFromString("2020-12-31 19:55:00");

        auto returnString = utils::time::TimeRangeParser().getCalendarTimeString(
            event.date_from, event.date_till, Version::abbrev, false);
        REQUIRE("2020-12-31 00:05:00" == TimePointToString(event.date_from));
        REQUIRE("2020-12-31 19:55:00" == TimePointToString(event.date_till));
        REQUIRE("12" == TimePointToHourString12H(event.date_from));
        REQUIRE("05" == TimePointToMinutesString(event.date_from));
        REQUIRE(returnString == "12:05 " + utils::localize.get(utils::time::Locale::getAM()));
    }

    SECTION("After noon time input - short version (mode12h)")
    {
        auto event      = EventsRecord();
        event.date_from = TimePointFromString("2020-12-31 12:05:00");
        event.date_till = TimePointFromString("2020-12-31 19:55:00");

        auto returnString = utils::time::TimeRangeParser().getCalendarTimeString(
            event.date_from, event.date_till, Version::abbrev, false);
        REQUIRE("2020-12-31 12:05:00" == TimePointToString(event.date_from));
        REQUIRE("2020-12-31 19:55:00" == TimePointToString(event.date_till));
        REQUIRE("12" == TimePointToHourString12H(event.date_from));
        REQUIRE("05" == TimePointToMinutesString(event.date_from));
        REQUIRE(returnString == "12:05 " + utils::localize.get(utils::time::Locale::getPM()));
    }

    SECTION("Time input (mode24h)")
    {
        auto event      = EventsRecord();
        event.date_from = TimePointFromString("2021-01-01 01:05:00");
        event.date_till = TimePointFromString("2021-01-01 19:55:00");

        auto returnString = utils::time::TimeRangeParser().getCalendarTimeString(
            event.date_from, event.date_till, Version::normal, true);
        REQUIRE("2021-01-01 01:05:00" == TimePointToString(event.date_from));
        REQUIRE("2021-01-01 19:55:00" == TimePointToString(event.date_till));
        REQUIRE("1" == TimePointToHourString24H(event.date_from));
        REQUIRE("05" == TimePointToMinutesString(event.date_from));
        REQUIRE("19" == TimePointToHourString24H(event.date_till));
        REQUIRE("55" == TimePointToMinutesString(event.date_till));
        REQUIRE(returnString == "1:05 - 19:55");
    }

    SECTION("Time input - short version (mode24h)")
    {
        auto event      = EventsRecord();
        event.date_from = TimePointFromString("2021-01-01 18:05:00");
        event.date_till = TimePointFromString("2021-01-01 19:55:00");

        auto returnString = utils::time::TimeRangeParser().getCalendarTimeString(
            event.date_from, event.date_till, Version::abbrev, true);
        REQUIRE("2021-01-01 18:05:00" == TimePointToString(event.date_from));
        REQUIRE("2021-01-01 19:55:00" == TimePointToString(event.date_till));
        REQUIRE("18" == TimePointToHourString24H(event.date_from));
        REQUIRE("05" == TimePointToMinutesString(event.date_from));
        REQUIRE(returnString == "18:05");
    }

    SECTION("All day time input")
    {
        auto event      = EventsRecord();
        event.date_from = TimePointFromString("2020-10-20 00:00:00");
        event.date_till = TimePointFromString("2020-10-20 23:59:00");

        auto returnString = utils::time::TimeRangeParser().getCalendarTimeString(
            event.date_from, event.date_till, Version::normal, false);
        REQUIRE("2020-10-20 00:00:00" == TimePointToString(event.date_from));
        REQUIRE("2020-10-20 23:59:00" == TimePointToString(event.date_till));
        REQUIRE(returnString == utils::localize.get("app_calendar_all_day"));
    }
}

A module-utils/time/TimeRangeParser.cpp => module-utils/time/TimeRangeParser.cpp +72 -0
@@ 0,0 1,72 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#include "TimeRangeParser.hpp"

namespace utils::time
{
    namespace
    {
        constexpr int max_hour    = 23;
        constexpr int max_minutes = 59;
    } // namespace

    std::string TimeRangeParser::AMPMtoString(bool isAm)
    {
        if (isAm) {
            return utils::localize.get(utils::time::Locale::getAM());
        }
        return utils::localize.get(utils::time::Locale::getPM());
    }

    std::string TimeRangeParser::getCalendarTimeString(TimePoint startDate,
                                                       TimePoint endDate,
                                                       Version version,
                                                       bool isMode24H)
    {
        auto startTime = TimePointToHourMinSec(startDate);
        auto endTime   = TimePointToHourMinSec(endDate);

        if (startTime.hours().count() == 0 && startTime.minutes().count() == 0 && endTime.hours().count() == max_hour &&
            endTime.minutes().count() == max_minutes) {
            return utils::localize.get("app_calendar_all_day");
        }
        else {
            bool startIsAm = true;
            bool endIsAm   = true;

            if (!isMode24H) {
                startIsAm = date::is_am(startTime.hours());
                endIsAm   = date::is_am(endTime.hours());
            }

            if (version == Version::abbrev) {
                if (!isMode24H) {
                    return TimePointToHourString12H(startDate) + ":" + TimePointToMinutesString(startDate) + " " +
                           AMPMtoString(startIsAm);
                }
                else {
                    return TimePointToHourString24H(startDate) + ":" + TimePointToMinutesString(startDate);
                }
            }
            else {
                if (!isMode24H) {
                    if (startIsAm != endIsAm) {
                        return TimePointToHourString12H(startDate) + ":" + TimePointToMinutesString(startDate) + " " +
                               AMPMtoString(startIsAm) + " - " + TimePointToHourString12H(endDate) + ":" +
                               TimePointToMinutesString(endDate) + " " + AMPMtoString(endIsAm);
                    }
                    else {
                        return TimePointToHourString12H(startDate) + ":" + TimePointToMinutesString(startDate) + " - " +
                               TimePointToHourString12H(endDate) + ":" + TimePointToMinutesString(endDate) + " " +
                               AMPMtoString(startIsAm);
                    }
                }
                else {
                    return TimePointToHourString24H(startDate) + ":" + TimePointToMinutesString(startDate) + " - " +
                           TimePointToHourString24H(endDate) + ":" + TimePointToMinutesString(endDate);
                }
            }
        }
    }
} // namespace utils::time

A module-utils/time/TimeRangeParser.hpp => module-utils/time/TimeRangeParser.hpp +28 -0
@@ 0,0 1,28 @@
// Copyright (c) 2017-2020, Mudita Sp. z.o.o. All rights reserved.
// For licensing, see https://github.com/mudita/MuditaOS/LICENSE.md

#pragma once
#include "Utils.hpp"
#include <module-apps/application-calendar/data/dateCommon.hpp>

namespace utils::time
{
    enum class Version
    {
        abbrev,
        normal
    };

    class TimeRangeParser
    {

      private:
        std::string AMPMtoString(bool isAm);

      public:
        std::string getCalendarTimeString(TimePoint startDate,
                                          TimePoint endDate,
                                          Version version = Version::normal,
                                          bool isMode24H  = false);
    };
} // namespace utils::time

M module-utils/time/time_conversion.cpp => module-utils/time/time_conversion.cpp +18 -0
@@ 234,6 234,24 @@ namespace utils::time
        }
        return UINT32_MAX;
    }
    uint32_t Timestamp::get_UTC_date_time_sub_value(GetParameters param)
    {
        std::tm tm = *std::gmtime(&time);
        switch (param) {
        case GetParameters::Hour:
            return tm.tm_hour;
        case GetParameters::Minute:
            return tm.tm_min;
        case GetParameters::Day:
            return tm.tm_mday;
        case GetParameters::Month:
            return tm.tm_mon + 1;
        case GetParameters::Year:
            return tm.tm_year + 1900;
        }
        return UINT32_MAX;
    }

    UTF8 Date::str(std::string format)
    {
        if (!format.empty()) {

M module-utils/time/time_conversion.hpp => module-utils/time/time_conversion.hpp +1 -0
@@ 137,6 137,7 @@ namespace utils

            UTF8 get_date_time_substr(GetParameters param);
            uint32_t get_date_time_sub_value(GetParameters param);
            uint32_t get_UTC_date_time_sub_value(GetParameters param);
        };

        /// helper class to operate on time now