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