From fe70a520b1f1cecdc3cc3ce74dfa84632f3a21b5 Mon Sep 17 00:00:00 2001 From: Haibo Date: Mon, 29 Oct 2018 13:36:09 +0800 Subject: [PATCH] add: Duration::Parse to format a duration --- core/e2dutil.h | 17 ++++++-- core/utils/Duration.cpp | 86 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 99 insertions(+), 4 deletions(-) diff --git a/core/e2dutil.h b/core/e2dutil.h index b3f5ef41..be76ad48 100644 --- a/core/e2dutil.h +++ b/core/e2dutil.h @@ -342,6 +342,8 @@ namespace easy2d // 5 秒: Duration::Second * 5 // 1.5 小时: Duration::Hour * 1.5 // 3 小时 45 分 15 秒: Duration::Hour * 3 + Duration::Minute * 45 + Duration::Second * 15 + // 时间段转化为秒: float s = duration.Seconds(); + // 时间段格式化: Duration d = Duration::Parse(L"1h35m"); // 1小时35分钟 // class Duration { @@ -358,18 +360,24 @@ namespace easy2d int milliseconds ); - // 获取毫秒数 + // 转化为毫秒 int Milliseconds() const; - // 获取秒数 + // 转化为秒 float Seconds() const; - // 获取分钟数 + // 转化为分钟 float Minutes() const; - // 获取小时数 + // 转化为小时 float Hours() const; + // 时间段格式化 + // 时间段字符串允许是有符号的浮点数, 并且带有时间单位后缀 + // 例如: "300ms", "-1.5h", "2h45m" + // 允许的时间单位有 "ms", "s", "m", "h" + static Duration Parse(const std::wstring& str); + bool operator== (const Duration &) const; bool operator!= (const Duration &) const; bool operator> (const Duration &) const; @@ -379,6 +387,7 @@ namespace easy2d Duration operator + (Duration const &) const; Duration operator - (Duration const &) const; + Duration operator - () const; Duration operator * (int) const; Duration operator * (float) const; Duration operator * (double) const; diff --git a/core/utils/Duration.cpp b/core/utils/Duration.cpp index 5e39406d..75c5a256 100644 --- a/core/utils/Duration.cpp +++ b/core/utils/Duration.cpp @@ -19,6 +19,7 @@ // THE SOFTWARE. #include "..\e2dutil.h" +#include const easy2d::Duration easy2d::Duration::Millisecond = easy2d::Duration(1); @@ -62,6 +63,85 @@ float easy2d::Duration::Hours() const return static_cast(hour) + static_cast(ms) / (60 * 60 * 1000.f); } +easy2d::Duration easy2d::Duration::Parse(const std::wstring & str) +{ + typedef std::map UnitMap; + static const auto regex = std::wregex(L"[-+]?([0-9]*(\\.[0-9]*)?[a-z]+)+"); + static const auto unit_map = UnitMap{{L"ms", Millisecond}, {L"s", Second}, {L"m", Minute}, {L"h", Hour}}; + + size_t len = str.length(); + size_t pos = 0; + bool negative = false; + Duration d; + + if (!std::regex_match(str, regex)) + { + E2D_WARNING("Duration::Parse: invalid duration"); + return std::move(Duration{}); + } + + if (str.empty() || str == L"0") { return std::move(Duration{}); } + + // 符号位 + if (str[0] == L'-' || str[0] == L'+') + { + negative = (str[0] == L'-'); + pos++; + } + + while (pos < len) + { + // 数值 + size_t i = pos; + for (; i < len; ++i) + { + wchar_t ch = str[i]; + if (!(ch == L'.' || L'0' <= ch && ch <= L'9')) + { + break; + } + } + + std::wstring num_str = str.substr(pos, i - pos); + pos = i; + + if (num_str.empty() || num_str == L".") + { + E2D_WARNING("Duration::Parse: invalid duration"); + return std::move(Duration{}); + } + + // 单位 + for (; i < len; ++i) + { + wchar_t ch = str[i]; + if (ch == L'.' || L'0' <= ch && ch <= L'9') + { + break; + } + } + + std::wstring unit_str = str.substr(pos, i - pos); + pos = i; + + if (unit_map.find(unit_str) == unit_map.end()) + { + E2D_WARNING("Duration::Parse: invalid duration"); + return std::move(Duration{}); + } + + double num = std::stod(num_str); + Duration unit = unit_map.at(unit_str); + d += unit * num; + } + + if (negative) + { + d.milliseconds_ = -d.milliseconds_; + } + return std::move(d); +} + bool easy2d::Duration::operator==(const Duration & other) const { return milliseconds_ == other.milliseconds_; @@ -104,6 +184,12 @@ easy2d::Duration easy2d::Duration::operator-(Duration const & other) const return std::move(d); } +easy2d::Duration easy2d::Duration::operator-() const +{ + Duration d(-milliseconds_); + return std::move(d); +} + easy2d::Duration easy2d::Duration::operator*(int value) const { Duration d(milliseconds_ * value);