mirror of https://github.com/JAJames/jessilib.git
Jessica James
3 years ago
2 changed files with 525 additions and 0 deletions
@ -0,0 +1,299 @@ |
|||
/**
|
|||
* Copyright (C) 2021 Jessica James. |
|||
* |
|||
* Permission to use, copy, modify, and/or distribute this software for any |
|||
* purpose with or without fee is hereby granted, provided that the above |
|||
* copyright notice and this permission notice appear in all copies. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
* |
|||
* Written by Jessica James <jessica.aj@outlook.com> |
|||
*/ |
|||
|
|||
#pragma once |
|||
|
|||
#include <chrono> |
|||
#include <string> |
|||
#include <string_view> |
|||
|
|||
namespace jessilib { |
|||
|
|||
namespace impl { |
|||
|
|||
constexpr const char* suffix_helper(const char* begin, const char* end, const char* ignored_suffix) { |
|||
while (begin != end |
|||
&& *begin == *ignored_suffix) { |
|||
++begin; |
|||
++ignored_suffix; |
|||
} |
|||
|
|||
return begin; |
|||
} |
|||
|
|||
} // namespace impl
|
|||
|
|||
// Base 10 only
|
|||
// y = year (31556952 seconds == 365.2425 day)
|
|||
// mo = month (2629746 seconds == year/12)
|
|||
// w = weeks
|
|||
// d[ay] = days
|
|||
// h[r] = hours
|
|||
// m[in] = minutes
|
|||
// s = seconds
|
|||
// ms = milliseconds
|
|||
// us = microseconds
|
|||
// ns = nanoseconds
|
|||
// trailing: DurationT
|
|||
|
|||
template<typename DurationT = std::chrono::seconds> |
|||
struct duration_from_string_result { |
|||
const char* itr{}; |
|||
DurationT duration{}; |
|||
}; |
|||
|
|||
// At time of writing, days, weeks, months, years seem inconsistently available
|
|||
using days = std::chrono::duration<std::chrono::hours::rep, std::ratio<86400>>; |
|||
using weeks = std::chrono::duration<std::chrono::hours::rep, std::ratio<604800>>; |
|||
using months = std::chrono::duration<std::chrono::hours::rep, std::ratio<2629746>>; |
|||
using years = std::chrono::duration<std::chrono::hours::rep, std::ratio<31556952>>; |
|||
|
|||
template<typename DurationT = std::chrono::seconds> |
|||
constexpr duration_from_string_result<DurationT> duration_from_string(const char* begin, const char* end) { |
|||
duration_from_string_result<DurationT> result{ begin, {} }; |
|||
auto& itr = result.itr; |
|||
|
|||
// Sanity check
|
|||
if (end <= itr) { |
|||
return result; |
|||
} |
|||
|
|||
while (itr != end) { |
|||
// Advance through any whitespace preceding type specifier
|
|||
while (*itr == ' ') { |
|||
++itr; |
|||
|
|||
if (itr == end) { |
|||
// no text remains
|
|||
return result; |
|||
} |
|||
} |
|||
|
|||
typename DurationT::rep segment{}; |
|||
|
|||
// Parse duration segment (i.e: [0-9]+[ms][]
|
|||
while (*itr >= '0' && *itr <= '9') { |
|||
segment *= 10; |
|||
segment += *itr - '0'; |
|||
++itr; |
|||
|
|||
if (itr == end) { |
|||
// end of string; always treat ending digits as base unit (DurationT)
|
|||
result.duration += DurationT{ segment }; |
|||
return result; |
|||
} |
|||
} |
|||
|
|||
// Advance past any whitespace preceding type specifier
|
|||
while (*itr == ' ') { |
|||
++itr; |
|||
|
|||
if (itr == end) { |
|||
// end of string; always treat ending digits as base unit (DurationT)
|
|||
result.duration += DurationT{ segment }; |
|||
return result; |
|||
} |
|||
} |
|||
|
|||
// after switch, 'itr' shall point to first unparsed character, or end
|
|||
switch (*itr) { |
|||
case 'y': // year
|
|||
++itr; // 'y'
|
|||
result.duration += std::chrono::duration_cast<DurationT>(years{ segment }); |
|||
|
|||
// "yr"
|
|||
if (itr != end |
|||
&& *itr == 'r') { |
|||
// ignore trailing 'r'
|
|||
++itr; |
|||
break; |
|||
} |
|||
|
|||
// "year"
|
|||
itr = impl::suffix_helper(itr, end, "ear"); |
|||
break; |
|||
|
|||
case 'w': // week
|
|||
++itr; // 'w'
|
|||
result.duration += std::chrono::duration_cast<DurationT>(weeks{ segment }); |
|||
|
|||
if (itr != end |
|||
&& *itr == 'k') { |
|||
// "wk"
|
|||
++itr; |
|||
break; |
|||
} |
|||
|
|||
// "week"
|
|||
itr = impl::suffix_helper(itr, end, "eek"); |
|||
break; |
|||
|
|||
case 'd': // day
|
|||
++itr; // 'd'
|
|||
result.duration += std::chrono::duration_cast<DurationT>(days{ segment }); |
|||
itr = impl::suffix_helper(itr, end, "ay"); |
|||
break; |
|||
|
|||
case 'h': // hour
|
|||
++itr; // 'h'
|
|||
result.duration += std::chrono::duration_cast<DurationT>(std::chrono::hours{ segment }); |
|||
|
|||
if (itr != end |
|||
&& *itr == 'r') { |
|||
// "hr"
|
|||
++itr; |
|||
break; |
|||
} |
|||
|
|||
// "hour"
|
|||
itr = impl::suffix_helper(itr, end, "our"); |
|||
break; |
|||
|
|||
case 'm': // min/month/milli
|
|||
++itr; // 'm'
|
|||
|
|||
if (itr == end) { |
|||
// "m" end of string; treat as minutes
|
|||
result.duration += std::chrono::duration_cast<DurationT>(std::chrono::minutes{ segment }); |
|||
return result; |
|||
} |
|||
|
|||
if (*itr == 'i') { |
|||
// "minutes" or "milliseconds"
|
|||
++itr; |
|||
|
|||
if (itr != end |
|||
&& *itr == 'n') { |
|||
// minutes
|
|||
result.duration += std::chrono::duration_cast<DurationT>(std::chrono::minutes{ segment }); |
|||
itr = impl::suffix_helper(itr, end, "nutes"); |
|||
break; |
|||
} |
|||
|
|||
// anything not starting with "min", assume milliseconds
|
|||
result.duration += std::chrono::duration_cast<DurationT>(std::chrono::milliseconds{ segment }); |
|||
itr = impl::suffix_helper(itr, end, "lliseconds"); |
|||
break; |
|||
} |
|||
|
|||
if (*itr == 's') { |
|||
// ms
|
|||
result.duration += std::chrono::duration_cast<DurationT>(std::chrono::milliseconds{ segment }); |
|||
++itr; |
|||
break; |
|||
} |
|||
|
|||
if (*itr == 'o') { |
|||
// mo
|
|||
result.duration += std::chrono::duration_cast<DurationT>(months{ segment }); |
|||
++itr; |
|||
|
|||
// "month"
|
|||
itr = impl::suffix_helper(itr, end, "nth"); |
|||
break; |
|||
} |
|||
|
|||
// Valid scenario for "m "; invalid specifier otherwise
|
|||
break; |
|||
|
|||
case 's': |
|||
++itr; // 's'
|
|||
result.duration += std::chrono::duration_cast<DurationT>(std::chrono::seconds{ segment }); |
|||
itr = impl::suffix_helper(itr, end, "econd"); |
|||
break; |
|||
|
|||
case 'u': // micro
|
|||
++itr; // 'u'
|
|||
result.duration += std::chrono::duration_cast<DurationT>(std::chrono::microseconds{ segment }); |
|||
itr = impl::suffix_helper(itr, end, "s"); |
|||
break; |
|||
|
|||
case 'n': // nano
|
|||
++itr; // 'n'
|
|||
result.duration += std::chrono::duration_cast<DurationT>(std::chrono::nanoseconds{ segment }); |
|||
itr = impl::suffix_helper(itr, end, "s"); |
|||
break; |
|||
|
|||
default: |
|||
// unexpected specifier; assume DurationT and cease parsing
|
|||
result.duration += DurationT{ segment }; |
|||
return result; |
|||
} |
|||
|
|||
if (itr == end) { |
|||
return result; |
|||
} |
|||
|
|||
// Remove any trailing 's' at end of unit (i.e: years, months, etc)
|
|||
if (*itr == 's') { |
|||
++itr; |
|||
} |
|||
} |
|||
|
|||
return result; |
|||
} |
|||
|
|||
template<typename DurationT = std::chrono::seconds> |
|||
constexpr duration_from_string_result<DurationT> duration_from_string(const std::string_view& in_duration) { |
|||
return duration_from_string<DurationT>(in_duration.data(), in_duration.data() + in_duration.size()); |
|||
} |
|||
|
|||
namespace literals { |
|||
|
|||
constexpr std::chrono::nanoseconds operator ""_duration_ns(const char* in_str, size_t in_str_length) { |
|||
return duration_from_string<std::chrono::nanoseconds>(in_str, in_str + in_str_length).duration; |
|||
} |
|||
|
|||
constexpr std::chrono::microseconds operator ""_duration_us(const char* in_str, size_t in_str_length) { |
|||
return duration_from_string<std::chrono::microseconds>(in_str, in_str + in_str_length).duration; |
|||
} |
|||
|
|||
constexpr std::chrono::milliseconds operator ""_duration_ms(const char* in_str, size_t in_str_length) { |
|||
return duration_from_string<std::chrono::milliseconds>(in_str, in_str + in_str_length).duration; |
|||
} |
|||
|
|||
constexpr std::chrono::seconds operator ""_duration_s(const char* in_str, size_t in_str_length) { |
|||
return duration_from_string<std::chrono::seconds>(in_str, in_str + in_str_length).duration; |
|||
} |
|||
|
|||
constexpr std::chrono::minutes operator ""_duration_m(const char* in_str, size_t in_str_length) { |
|||
return duration_from_string<std::chrono::minutes>(in_str, in_str + in_str_length).duration; |
|||
} |
|||
|
|||
constexpr std::chrono::hours operator ""_duration_h(const char* in_str, size_t in_str_length) { |
|||
return duration_from_string<std::chrono::hours>(in_str, in_str + in_str_length).duration; |
|||
} |
|||
|
|||
constexpr days operator ""_duration_d(const char* in_str, size_t in_str_length) { |
|||
return duration_from_string<days>(in_str, in_str + in_str_length).duration; |
|||
} |
|||
|
|||
constexpr weeks operator ""_duration_w(const char* in_str, size_t in_str_length) { |
|||
return duration_from_string<weeks>(in_str, in_str + in_str_length).duration; |
|||
} |
|||
|
|||
constexpr months operator ""_duration_mo(const char* in_str, size_t in_str_length) { |
|||
return duration_from_string<months>(in_str, in_str + in_str_length).duration; |
|||
} |
|||
|
|||
constexpr years operator ""_duration_y(const char* in_str, size_t in_str_length) { |
|||
return duration_from_string<years>(in_str, in_str + in_str_length).duration; |
|||
} |
|||
|
|||
} // namespace literals
|
|||
} // namespace jessilib
|
@ -0,0 +1,226 @@ |
|||
/**
|
|||
* Copyright (C) 2018 Jessica James. |
|||
* |
|||
* Permission to use, copy, modify, and/or distribute this software for any |
|||
* purpose with or without fee is hereby granted, provided that the above |
|||
* copyright notice and this permission notice appear in all copies. |
|||
* |
|||
* THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES |
|||
* WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF |
|||
* MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY |
|||
* SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES |
|||
* WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION |
|||
* OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN |
|||
* CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. |
|||
* |
|||
* Written by Jessica James <jessica.aj@outlook.com> |
|||
*/ |
|||
|
|||
#include "duration.hpp" |
|||
#include "test.hpp" |
|||
|
|||
using namespace jessilib; |
|||
using namespace std::literals; |
|||
using namespace jessilib::literals; |
|||
|
|||
/*
|
|||
* ns |
|||
* us |
|||
* ms |
|||
* s |
|||
* m |
|||
* h |
|||
* d |
|||
* w |
|||
* mo |
|||
* y |
|||
*/ |
|||
|
|||
// Basic compile-time tests
|
|||
static_assert("1234ns"_duration_ns.count() == 1234, "1234ns Test Failed"); |
|||
static_assert("1234us"_duration_us.count() == 1234, "1234us Test Failed"); |
|||
static_assert("1234ms"_duration_ms.count() == 1234, "1234ms Test Failed"); |
|||
static_assert("1234s"_duration_s.count() == 1234, "1234s Test Failed"); |
|||
static_assert("1234m"_duration_m.count() == 1234, "1234m Test Failed"); |
|||
static_assert("1234h"_duration_h.count() == 1234, "1234h Test Failed"); |
|||
static_assert("1234d"_duration_d.count() == 1234, "1234d Test Failed"); |
|||
static_assert("1234w"_duration_w.count() == 1234, "1234w Test Failed"); |
|||
static_assert("1234mo"_duration_mo.count() == 1234, "1234mo Test Failed"); |
|||
static_assert("1234y"_duration_y.count() == 1234, "1234y Test Failed"); |
|||
|
|||
// Ensure string_view variant compiles
|
|||
static_assert(duration_from_string("1234s"sv).duration.count() == 1234, "1234s string_view test failed"); |
|||
|
|||
TEST(duration, as_seconds) { |
|||
EXPECT_EQ(duration_from_string("1234"sv).duration.count(), 1234); |
|||
EXPECT_EQ(duration_from_string("0s"sv).duration.count(), 0); |
|||
EXPECT_EQ(duration_from_string("1s"sv).duration.count(), 1); |
|||
EXPECT_EQ(duration_from_string("5000ms"sv).duration.count(), 5); |
|||
EXPECT_EQ(duration_from_string("5000000us"sv).duration.count(), 5); |
|||
EXPECT_EQ(duration_from_string("5000000000ns"sv).duration.count(), 5); |
|||
EXPECT_EQ(duration_from_string("1h"sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string("1hr"sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string("1hour"sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string("1hours"sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string("1hrs"sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string("1d"sv).duration.count(), 86400); |
|||
EXPECT_EQ(duration_from_string("1day"sv).duration.count(), 86400); |
|||
EXPECT_EQ(duration_from_string("1days"sv).duration.count(), 86400); |
|||
EXPECT_EQ(duration_from_string("1w"sv).duration.count(), 604800); |
|||
EXPECT_EQ(duration_from_string("1week"sv).duration.count(), 604800); |
|||
EXPECT_EQ(duration_from_string("1weeks"sv).duration.count(), 604800); |
|||
EXPECT_EQ(duration_from_string("1mo"sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string("1mon"sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string("1month"sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string("1months"sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string("1y"sv).duration.count(), 31556952); |
|||
EXPECT_EQ(duration_from_string("1year"sv).duration.count(), 31556952); |
|||
EXPECT_EQ(duration_from_string("1years"sv).duration.count(), 31556952); |
|||
} |
|||
|
|||
TEST(duration, as_seconds_spaced) { |
|||
EXPECT_EQ(duration_from_string("0 s"sv).duration.count(), 0); |
|||
EXPECT_EQ(duration_from_string("1 s"sv).duration.count(), 1); |
|||
EXPECT_EQ(duration_from_string("5000 ms"sv).duration.count(), 5); |
|||
EXPECT_EQ(duration_from_string("5000000 us"sv).duration.count(), 5); |
|||
EXPECT_EQ(duration_from_string("5000000000 ns"sv).duration.count(), 5); |
|||
EXPECT_EQ(duration_from_string("1 h"sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string("1 hr"sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string("1 hour"sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string("1 hours"sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string("1 hrs"sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string("1 d"sv).duration.count(), 86400); |
|||
EXPECT_EQ(duration_from_string("1 day"sv).duration.count(), 86400); |
|||
EXPECT_EQ(duration_from_string("1 days"sv).duration.count(), 86400); |
|||
EXPECT_EQ(duration_from_string("1 w"sv).duration.count(), 604800); |
|||
EXPECT_EQ(duration_from_string("1 week"sv).duration.count(), 604800); |
|||
EXPECT_EQ(duration_from_string("1 weeks"sv).duration.count(), 604800); |
|||
EXPECT_EQ(duration_from_string("1 mo"sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string("1 mon"sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string("1 month"sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string("1 months"sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string("1 y"sv).duration.count(), 31556952); |
|||
EXPECT_EQ(duration_from_string("1 year"sv).duration.count(), 31556952); |
|||
EXPECT_EQ(duration_from_string("1 years"sv).duration.count(), 31556952); |
|||
} |
|||
|
|||
TEST(duration, as_seconds_front_spaced) { |
|||
EXPECT_EQ(duration_from_string(" 1234"sv).duration.count(), 1234); |
|||
EXPECT_EQ(duration_from_string(" 0s"sv).duration.count(), 0); |
|||
EXPECT_EQ(duration_from_string(" 1s"sv).duration.count(), 1); |
|||
EXPECT_EQ(duration_from_string(" 5000ms"sv).duration.count(), 5); |
|||
EXPECT_EQ(duration_from_string(" 5000000us"sv).duration.count(), 5); |
|||
EXPECT_EQ(duration_from_string(" 5000000000ns"sv).duration.count(), 5); |
|||
EXPECT_EQ(duration_from_string(" 1h"sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string(" 1hr"sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string(" 1hour"sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string(" 1hours"sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string(" 1hrs"sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string(" 1d"sv).duration.count(), 86400); |
|||
EXPECT_EQ(duration_from_string(" 1day"sv).duration.count(), 86400); |
|||
EXPECT_EQ(duration_from_string(" 1days"sv).duration.count(), 86400); |
|||
EXPECT_EQ(duration_from_string(" 1w"sv).duration.count(), 604800); |
|||
EXPECT_EQ(duration_from_string(" 1week"sv).duration.count(), 604800); |
|||
EXPECT_EQ(duration_from_string(" 1weeks"sv).duration.count(), 604800); |
|||
EXPECT_EQ(duration_from_string(" 1mo"sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string(" 1mon"sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string(" 1month"sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string(" 1months"sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string(" 1y"sv).duration.count(), 31556952); |
|||
EXPECT_EQ(duration_from_string(" 1year"sv).duration.count(), 31556952); |
|||
EXPECT_EQ(duration_from_string(" 1years"sv).duration.count(), 31556952); |
|||
} |
|||
|
|||
TEST(duration, as_seconds_back_spaced) { |
|||
EXPECT_EQ(duration_from_string("1234 "sv).duration.count(), 1234); |
|||
EXPECT_EQ(duration_from_string("0s "sv).duration.count(), 0); |
|||
EXPECT_EQ(duration_from_string("1s "sv).duration.count(), 1); |
|||
EXPECT_EQ(duration_from_string("5000ms "sv).duration.count(), 5); |
|||
EXPECT_EQ(duration_from_string("5000000us "sv).duration.count(), 5); |
|||
EXPECT_EQ(duration_from_string("5000000000ns "sv).duration.count(), 5); |
|||
EXPECT_EQ(duration_from_string("1h "sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string("1hr "sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string("1hour "sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string("1hours "sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string("1hrs "sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string("1d "sv).duration.count(), 86400); |
|||
EXPECT_EQ(duration_from_string("1day "sv).duration.count(), 86400); |
|||
EXPECT_EQ(duration_from_string("1days "sv).duration.count(), 86400); |
|||
EXPECT_EQ(duration_from_string("1w "sv).duration.count(), 604800); |
|||
EXPECT_EQ(duration_from_string("1week "sv).duration.count(), 604800); |
|||
EXPECT_EQ(duration_from_string("1weeks "sv).duration.count(), 604800); |
|||
EXPECT_EQ(duration_from_string("1mo "sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string("1mon "sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string("1month "sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string("1months "sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string("1y "sv).duration.count(), 31556952); |
|||
EXPECT_EQ(duration_from_string("1year "sv).duration.count(), 31556952); |
|||
EXPECT_EQ(duration_from_string("1years "sv).duration.count(), 31556952); |
|||
} |
|||
|
|||
TEST(duration, as_seconds_all_spaced) { |
|||
EXPECT_EQ(duration_from_string(" 1234 "sv).duration.count(), 1234); |
|||
EXPECT_EQ(duration_from_string(" 0 s "sv).duration.count(), 0); |
|||
EXPECT_EQ(duration_from_string(" 1 s "sv).duration.count(), 1); |
|||
EXPECT_EQ(duration_from_string(" 5000 ms "sv).duration.count(), 5); |
|||
EXPECT_EQ(duration_from_string(" 5000000 us "sv).duration.count(), 5); |
|||
EXPECT_EQ(duration_from_string(" 5000000000 ns "sv).duration.count(), 5); |
|||
EXPECT_EQ(duration_from_string(" 1 h "sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string(" 1 hr "sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string(" 1 hour "sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string(" 1 hours "sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string(" 1 hrs "sv).duration.count(), 3600); |
|||
EXPECT_EQ(duration_from_string(" 1 d "sv).duration.count(), 86400); |
|||
EXPECT_EQ(duration_from_string(" 1 day "sv).duration.count(), 86400); |
|||
EXPECT_EQ(duration_from_string(" 1 days "sv).duration.count(), 86400); |
|||
EXPECT_EQ(duration_from_string(" 1 w "sv).duration.count(), 604800); |
|||
EXPECT_EQ(duration_from_string(" 1 week "sv).duration.count(), 604800); |
|||
EXPECT_EQ(duration_from_string(" 1 weeks "sv).duration.count(), 604800); |
|||
EXPECT_EQ(duration_from_string(" 1 mo "sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string(" 1 mon "sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string(" 1 month "sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string(" 1 months "sv).duration.count(), 2629746); |
|||
EXPECT_EQ(duration_from_string(" 1 y "sv).duration.count(), 31556952); |
|||
EXPECT_EQ(duration_from_string(" 1 year "sv).duration.count(), 31556952); |
|||
EXPECT_EQ(duration_from_string(" 1 years "sv).duration.count(), 31556952); |
|||
} |
|||
|
|||
template<typename DurationT> |
|||
constexpr std::chrono::seconds to_seconds(DurationT in_duration) { |
|||
return std::chrono::duration_cast<std::chrono::seconds>(in_duration); |
|||
} |
|||
|
|||
TEST(duration, combinations) { |
|||
EXPECT_EQ(duration_from_string("1d 4 weeks"sv).duration.count(), |
|||
to_seconds(days{1} + weeks{4}).count()); |
|||
EXPECT_EQ(duration_from_string("1d 4 weeks 1 mon"sv).duration.count(), |
|||
to_seconds(days{1} + weeks{4} + months{1}).count()); |
|||
EXPECT_EQ(duration_from_string("1d 4 weeks 1 mon 4 min"sv).duration.count(), |
|||
to_seconds(days{1} + weeks{4} + months{1} + 4min).count()); |
|||
EXPECT_EQ(duration_from_string("1d 4 weeks 1 mon 4 min 36 sec"sv).duration.count(), |
|||
to_seconds(days{1} + weeks{4} + months{1} + 4min + 36s).count()); |
|||
EXPECT_EQ(duration_from_string("1d 4 weeks 1 mon 4 min 36 sec 12hr"sv).duration.count(), |
|||
to_seconds(days{1} + weeks{4} + months{1} + 4min + 36s + 12h).count()); |
|||
EXPECT_EQ(duration_from_string("1d 4 weeks 1 mon 4 min 36 sec 12hr 5s"sv).duration.count(), |
|||
to_seconds(days{1} + weeks{4} + months{1} + 4min + 36s + 12h + 5s).count()); |
|||
|
|||
// Consider refactoring such that the expressions are equal without usage of to_seconds for types smaller than seconds
|
|||
EXPECT_EQ(duration_from_string("1d 4 weeks 1 mon 4 min 36 sec 12hr 5s 4900ms"sv).duration.count(), |
|||
to_seconds(days{1} + weeks{4} + months{1} + 4min + 36s + 12h + 5s + to_seconds(4900ms)).count()); |
|||
EXPECT_EQ(duration_from_string("1d 4 weeks 1 mon 4 min 36 sec 12hr 5s 4900ms 6900000us"sv).duration.count(), |
|||
to_seconds(days{1} + weeks{4} + months{1} + 4min + 36s + 12h + 5s + to_seconds(4900ms) + to_seconds(6900000us)).count()); |
|||
EXPECT_EQ(duration_from_string("1d 4 weeks 1 mon 4 min 36 sec 12hr 5s 4900ms 6900000us 900000000ns"sv).duration.count(), |
|||
to_seconds(days{1} + weeks{4} + months{1} + 4min + 36s + 12h + 5s + to_seconds(4900ms) + to_seconds(6900000us) + to_seconds(900000000ns)).count()); |
|||
EXPECT_EQ(duration_from_string("1d 4 weeks 1 mon 4 min 36 sec 12hr 5s 4900ms 6900000us 900000000ns 7days 6years"sv).duration.count(), |
|||
to_seconds(days{1} + weeks{4} + months{1} + 4min + 36s + 12h + 5s + to_seconds(4900ms) + to_seconds(6900000us) + to_seconds(900000000ns) + days{7} + years {6}).count()); |
|||
} |
|||
|
|||
TEST(duration, invalid) { |
|||
EXPECT_EQ(duration_from_string("Jessica was here"sv).duration.count(),0); |
|||
EXPECT_EQ(duration_from_string("and here"sv).duration.count(),0); |
|||
EXPECT_EQ(duration_from_string("second guessing code"sv).duration.count(),0); |
|||
EXPECT_EQ(duration_from_string("year round"sv).duration.count(),0); |
|||
|
|||
EXPECT_EQ(duration_from_string("1yr 3 da 4 mi invalid 77 months"sv).duration.count(), |
|||
to_seconds(years{1} + days{3}).count()); // "4 mi" is actually valid, but is rounded down to zero on conversion
|
|||
} |
Loading…
Reference in new issue