Add uniform naming for temporal type properties (#246)

This commit is contained in:
Kostas Kyrimis 2021-10-02 16:14:27 +02:00 committed by GitHub
parent 18b801a722
commit 7e82cc6550
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 271 additions and 267 deletions

View File

@ -1080,9 +1080,9 @@ TypedValue Date(const TypedValue *args, int64_t nargs, const FunctionContext &ct
utils::DateParameters date_parameters;
using namespace std::literals;
std::unordered_map parameter_mappings = {std::pair{"year"sv, &date_parameters.years},
std::pair{"month"sv, &date_parameters.months},
std::pair{"day"sv, &date_parameters.days}};
std::unordered_map parameter_mappings = {std::pair{"year"sv, &date_parameters.year},
std::pair{"month"sv, &date_parameters.month},
std::pair{"day"sv, &date_parameters.day}};
MapNumericParameters<Integer>(parameter_mappings, args[0].ValueMap());
return TypedValue(utils::Date(date_parameters), ctx.memory);
@ -1104,11 +1104,11 @@ TypedValue LocalTime(const TypedValue *args, int64_t nargs, const FunctionContex
using namespace std::literals;
std::unordered_map parameter_mappings{
std::pair{"hour"sv, &local_time_parameters.hours},
std::pair{"minute"sv, &local_time_parameters.minutes},
std::pair{"second"sv, &local_time_parameters.seconds},
std::pair{"millisecond"sv, &local_time_parameters.milliseconds},
std::pair{"microsecond"sv, &local_time_parameters.microseconds},
std::pair{"hour"sv, &local_time_parameters.hour},
std::pair{"minute"sv, &local_time_parameters.minute},
std::pair{"second"sv, &local_time_parameters.second},
std::pair{"millisecond"sv, &local_time_parameters.millisecond},
std::pair{"microsecond"sv, &local_time_parameters.microsecond},
};
MapNumericParameters<Integer>(parameter_mappings, args[0].ValueMap());
@ -1131,14 +1131,14 @@ TypedValue LocalDateTime(const TypedValue *args, int64_t nargs, const FunctionCo
utils::LocalTimeParameters local_time_parameters;
using namespace std::literals;
std::unordered_map parameter_mappings{
std::pair{"year"sv, &date_parameters.years},
std::pair{"month"sv, &date_parameters.months},
std::pair{"day"sv, &date_parameters.days},
std::pair{"hour"sv, &local_time_parameters.hours},
std::pair{"minute"sv, &local_time_parameters.minutes},
std::pair{"second"sv, &local_time_parameters.seconds},
std::pair{"millisecond"sv, &local_time_parameters.milliseconds},
std::pair{"microsecond"sv, &local_time_parameters.microseconds},
std::pair{"year"sv, &date_parameters.year},
std::pair{"month"sv, &date_parameters.month},
std::pair{"day"sv, &date_parameters.day},
std::pair{"hour"sv, &local_time_parameters.hour},
std::pair{"minute"sv, &local_time_parameters.minute},
std::pair{"second"sv, &local_time_parameters.second},
std::pair{"millisecond"sv, &local_time_parameters.millisecond},
std::pair{"microsecond"sv, &local_time_parameters.microsecond},
};
MapNumericParameters<Integer>(parameter_mappings, args[0].ValueMap());
@ -1154,12 +1154,12 @@ TypedValue Duration(const TypedValue *args, int64_t nargs, const FunctionContext
utils::DurationParameters duration_parameters;
using namespace std::literals;
std::unordered_map parameter_mappings{std::pair{"day"sv, &duration_parameters.days},
std::pair{"hour"sv, &duration_parameters.hours},
std::pair{"minute"sv, &duration_parameters.minutes},
std::pair{"second"sv, &duration_parameters.seconds},
std::pair{"millisecond"sv, &duration_parameters.milliseconds},
std::pair{"microsecond"sv, &duration_parameters.microseconds}};
std::unordered_map parameter_mappings{std::pair{"day"sv, &duration_parameters.day},
std::pair{"hour"sv, &duration_parameters.hour},
std::pair{"minute"sv, &duration_parameters.minute},
std::pair{"second"sv, &duration_parameters.second},
std::pair{"millisecond"sv, &duration_parameters.millisecond},
std::pair{"microsecond"sv, &duration_parameters.microsecond}};
MapNumericParameters<Number>(parameter_mappings, args[0].ValueMap());
return TypedValue(utils::Duration(duration_parameters), ctx.memory);
}

View File

@ -250,54 +250,54 @@ class ExpressionEvaluator : public ExpressionVisitor<TypedValue> {
auto expression_result = property_lookup.expression_->Accept(*this);
auto maybe_date = [this](const auto &date, const auto &prop_name) -> std::optional<TypedValue> {
if (prop_name == "year") {
return TypedValue(date.years, ctx_->memory);
return TypedValue(date.year, ctx_->memory);
}
if (prop_name == "month") {
return TypedValue(date.months, ctx_->memory);
return TypedValue(date.month, ctx_->memory);
}
if (prop_name == "day") {
return TypedValue(date.days, ctx_->memory);
return TypedValue(date.day, ctx_->memory);
}
return std::nullopt;
};
auto maybe_local_time = [this](const auto &lt, const auto &prop_name) -> std::optional<TypedValue> {
if (prop_name == "hour") {
return TypedValue(lt.hours, ctx_->memory);
return TypedValue(lt.hour, ctx_->memory);
}
if (prop_name == "minute") {
return TypedValue(lt.minutes, ctx_->memory);
return TypedValue(lt.minute, ctx_->memory);
}
if (prop_name == "seconds") {
return TypedValue(lt.seconds, ctx_->memory);
if (prop_name == "second") {
return TypedValue(lt.second, ctx_->memory);
}
if (prop_name == "milliseconds") {
return TypedValue(lt.milliseconds, ctx_->memory);
if (prop_name == "millisecond") {
return TypedValue(lt.millisecond, ctx_->memory);
}
if (prop_name == "microseconds") {
return TypedValue(lt.microseconds, ctx_->memory);
if (prop_name == "microsecond") {
return TypedValue(lt.microsecond, ctx_->memory);
}
return std::nullopt;
};
auto maybe_duration = [this](const auto &dur, const auto &prop_name) -> std::optional<TypedValue> {
if (prop_name == "days") {
if (prop_name == "day") {
return TypedValue(dur.Days(), ctx_->memory);
}
if (prop_name == "hours") {
if (prop_name == "hour") {
return TypedValue(dur.SubDaysAsHours(), ctx_->memory);
}
if (prop_name == "minutes") {
if (prop_name == "minute") {
return TypedValue(dur.SubDaysAsMinutes(), ctx_->memory);
}
if (prop_name == "seconds") {
if (prop_name == "second") {
return TypedValue(dur.SubDaysAsSeconds(), ctx_->memory);
}
if (prop_name == "milliseconds") {
if (prop_name == "millisecond") {
return TypedValue(dur.SubDaysAsMilliseconds(), ctx_->memory);
}
if (prop_name == "microseconds") {
if (prop_name == "microsecond") {
return TypedValue(dur.SubDaysAsMicroseconds(), ctx_->memory);
}
if (prop_name == "nanoseconds") {
if (prop_name == "nanosecond") {
return TypedValue(dur.SubDaysAsNanoseconds(), ctx_->memory);
}
return std::nullopt;

View File

@ -1163,15 +1163,15 @@ mgp_error mgp_date_equal(mgp_date *first, mgp_date *second, int *result) {
}
mgp_error mgp_date_get_year(mgp_date *date, int *year) {
return WrapExceptions([date] { return date->date.years; }, year);
return WrapExceptions([date] { return date->date.year; }, year);
}
mgp_error mgp_date_get_month(mgp_date *date, int *month) {
return WrapExceptions([date] { return date->date.months; }, month);
return WrapExceptions([date] { return date->date.month; }, month);
}
mgp_error mgp_date_get_day(mgp_date *date, int *day) {
return WrapExceptions([date] { return date->date.days; }, day);
return WrapExceptions([date] { return date->date.day; }, day);
}
mgp_error mgp_date_timestamp(mgp_date *date, int64_t *timestamp) {
@ -1218,23 +1218,23 @@ mgp_error mgp_local_time_equal(mgp_local_time *first, mgp_local_time *second, in
}
mgp_error mgp_local_time_get_hour(mgp_local_time *local_time, int *hour) {
return WrapExceptions([local_time] { return local_time->local_time.hours; }, hour);
return WrapExceptions([local_time] { return local_time->local_time.hour; }, hour);
}
mgp_error mgp_local_time_get_minue(mgp_local_time *local_time, int *minute) {
return WrapExceptions([local_time] { return local_time->local_time.minutes; }, minute);
return WrapExceptions([local_time] { return local_time->local_time.minute; }, minute);
}
mgp_error mgp_local_time_get_second(mgp_local_time *local_time, int *second) {
return WrapExceptions([local_time] { return local_time->local_time.seconds; }, second);
return WrapExceptions([local_time] { return local_time->local_time.second; }, second);
}
mgp_error mgp_local_time_get_millisecond(mgp_local_time *local_time, int *millisecond) {
return WrapExceptions([local_time] { return local_time->local_time.milliseconds; }, millisecond);
return WrapExceptions([local_time] { return local_time->local_time.millisecond; }, millisecond);
}
mgp_error mgp_local_time_get_microsecond(mgp_local_time *local_time, int *microsecond) {
return WrapExceptions([local_time] { return local_time->local_time.microseconds; }, microsecond);
return WrapExceptions([local_time] { return local_time->local_time.microsecond; }, microsecond);
}
mgp_error mgp_local_time_timestamp(mgp_local_time *local_time, int64_t *timestamp) {
@ -1297,36 +1297,36 @@ mgp_error mgp_local_date_time_equal(mgp_local_date_time *first, mgp_local_date_t
}
mgp_error mgp_local_date_time_get_year(mgp_local_date_time *local_date_time, int *year) {
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.date.years; }, year);
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.date.year; }, year);
}
mgp_error mgp_local_date_time_get_month(mgp_local_date_time *local_date_time, int *month) {
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.date.months; }, month);
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.date.month }, month);
}
mgp_error mgp_local_date_time_get_day(mgp_local_date_time *local_date_time, int *day) {
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.date.days; }, day);
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.date.day; }, day);
}
mgp_error mgp_local_date_time_get_hour(mgp_local_date_time *local_date_time, int *hour) {
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.local_time.hours; }, hour);
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.local_time.hour; }, hour);
}
mgp_error mgp_local_date_time_get_minute(mgp_local_date_time *local_date_time, int *minute) {
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.local_time.minutes; }, minute);
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.local_time.minute; }, minute);
}
mgp_error mgp_local_date_time_get_second(mgp_local_date_time *local_date_time, int *second) {
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.local_time.seconds; }, second);
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.local_time.second; }, second);
}
mgp_error mgp_local_date_time_get_millisecond(mgp_local_date_time *local_date_time, int *millisecond) {
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.local_time.milliseconds; },
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.local_time.millisecond; },
millisecond);
}
mgp_error mgp_local_date_time_get_microsecond(mgp_local_date_time *local_date_time, int *microsecond) {
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.local_time.microseconds; },
return WrapExceptions([local_date_time] { return local_date_time->local_date_time.local_time.microsecond; },
microsecond);
}

View File

@ -116,7 +116,7 @@ struct mgp_value {
};
inline utils::DateParameters MapDateParameters(const mgp_date_parameters *parameters) {
return {.years = parameters->year, .months = parameters->month, .days = parameters->day};
return {.year = parameters->year, .month = parameters->month, .day = parameters->day};
}
struct mgp_date {
@ -160,11 +160,11 @@ struct mgp_date {
};
inline utils::LocalTimeParameters MapLocalTimeParameters(const mgp_local_time_parameters *parameters) {
return {.hours = parameters->hour,
.minutes = parameters->minute,
.seconds = parameters->second,
.milliseconds = parameters->millisecond,
.microseconds = parameters->microsecond};
return {.hour = parameters->hour,
.minute = parameters->minute,
.second = parameters->second,
.millisecond = parameters->millisecond,
.microsecond = parameters->microsecond};
}
struct mgp_local_time {
@ -264,12 +264,12 @@ struct mgp_local_date_time {
};
inline utils::DurationParameters MapDurationParameters(const mgp_duration_parameters *parameters) {
return {.days = parameters->day,
.hours = parameters->hour,
.minutes = parameters->minute,
.seconds = parameters->second,
.milliseconds = parameters->millisecond,
.microseconds = parameters->microsecond};
return {.day = parameters->day,
.hour = parameters->hour,
.minute = parameters->minute,
.second = parameters->second,
.millisecond = parameters->millisecond,
.microsecond = parameters->microsecond};
}
struct mgp_duration {

View File

@ -2071,21 +2071,21 @@ py::Object MgpValueToPyObject(const mgp_value &value, PyGraph *py_graph) {
}
case MGP_VALUE_TYPE_DATE: {
const auto &date = value.date_v->date;
py::Object py_date(PyDate_FromDate(date.years, date.months, date.days));
py::Object py_date(PyDate_FromDate(date.year, date.month, date.day));
return py_date;
}
case MGP_VALUE_TYPE_LOCAL_TIME: {
const auto &local_time = value.local_time_v->local_time;
py::Object py_local_time(PyTime_FromTime(local_time.hours, local_time.minutes, local_time.seconds,
local_time.milliseconds * 1000 + local_time.microseconds));
py::Object py_local_time(PyTime_FromTime(local_time.hour, local_time.minute, local_time.second,
local_time.millisecond * 1000 + local_time.microsecond));
return py_local_time;
}
case MGP_VALUE_TYPE_LOCAL_DATE_TIME: {
const auto &local_time = value.local_date_time_v->local_date_time.local_time;
const auto &date = value.local_date_time_v->local_date_time.date;
py::Object py_local_date_time(
PyDateTime_FromDateAndTime(date.years, date.months, date.days, local_time.hours, local_time.minutes,
local_time.seconds, local_time.milliseconds * 1000 + local_time.microseconds));
PyDateTime_FromDateAndTime(date.year, date.month, date.day, local_time.hour, local_time.minute,
local_time.second, local_time.millisecond * 1000 + local_time.microsecond));
return py_local_date_time;
}
case MGP_VALUE_TYPE_DURATION: {

View File

@ -40,32 +40,32 @@ Date::Date(const int64_t microseconds) {
const auto chrono_micros = chrono::microseconds(microseconds);
const auto s_days = chrono::sys_days(chrono::duration_cast<chrono::days>(chrono_micros));
const auto date = chrono::year_month_day(s_days);
years = static_cast<int>(date.year());
months = static_cast<unsigned>(date.month());
days = static_cast<unsigned>(date.day());
year = static_cast<int>(date.year());
month = static_cast<unsigned>(date.month());
day = static_cast<unsigned>(date.day());
}
Date::Date(const DateParameters &date_parameters) {
if (!IsInBounds(0, 9999, date_parameters.years)) {
if (!IsInBounds(0, 9999, date_parameters.year)) {
throw temporal::InvalidArgumentException(
"Creating a Date with invalid year parameter. The value should be an integer between 0 and 9999.");
}
if (!IsInBounds(1, 12, date_parameters.months)) {
if (!IsInBounds(1, 12, date_parameters.month)) {
throw temporal::InvalidArgumentException(
"Creating a Date with invalid month parameter. The value should be an integer between 1 and 12.");
}
if (!IsInBounds(1, 31, date_parameters.days) ||
!IsValidDay(date_parameters.days, date_parameters.months, date_parameters.years)) {
if (!IsInBounds(1, 31, date_parameters.day) ||
!IsValidDay(date_parameters.day, date_parameters.month, date_parameters.year)) {
throw temporal::InvalidArgumentException(
"Creating a Date with invalid day parameter. The value should be an integer between 1 and 31, depending on the "
"month and year.");
}
years = date_parameters.years;
months = date_parameters.months;
days = date_parameters.days;
year = date_parameters.year;
month = date_parameters.month;
day = date_parameters.day;
}
namespace {
@ -140,7 +140,7 @@ std::pair<DateParameters, bool> ParseDateParameters(std::string_view date_string
if (!maybe_year) {
throw temporal::InvalidArgumentException("Invalid year in the string. {}", kSupportedDateFormatsHelpMessage);
}
date_parameters.years = *maybe_year;
date_parameters.year = *maybe_year;
date_string.remove_prefix(4);
bool is_extended_format = false;
@ -153,7 +153,7 @@ std::pair<DateParameters, bool> ParseDateParameters(std::string_view date_string
if (!maybe_month) {
throw temporal::InvalidArgumentException("Invalid month in the string. {}", kSupportedDateFormatsHelpMessage);
}
date_parameters.months = *maybe_month;
date_parameters.month = *maybe_month;
date_string.remove_prefix(2);
if (!date_string.empty()) {
@ -168,7 +168,7 @@ std::pair<DateParameters, bool> ParseDateParameters(std::string_view date_string
if (!maybe_day) {
throw temporal::InvalidArgumentException("Invalid month in the string. {}", kSupportedDateFormatsHelpMessage);
}
date_parameters.days = *maybe_day;
date_parameters.day = *maybe_day;
date_string.remove_prefix(2);
}
@ -181,16 +181,16 @@ std::pair<DateParameters, bool> ParseDateParameters(std::string_view date_string
int64_t Date::MicrosecondsSinceEpoch() const {
namespace chrono = std::chrono;
return chrono::duration_cast<chrono::microseconds>(utils::DaysSinceEpoch(years, months, days)).count();
return chrono::duration_cast<chrono::microseconds>(utils::DaysSinceEpoch(year, month, day)).count();
}
int64_t Date::DaysSinceEpoch() const { return utils::DaysSinceEpoch(years, months, days).count(); }
int64_t Date::DaysSinceEpoch() const { return utils::DaysSinceEpoch(year, month, day).count(); }
size_t DateHash::operator()(const Date &date) const {
utils::HashCombine<uint64_t, uint64_t> hasher;
size_t result = hasher(0, date.years);
result = hasher(result, date.months);
result = hasher(result, date.days);
size_t result = hasher(0, date.year);
result = hasher(result, date.month);
result = hasher(result, date.day);
return result;
}
@ -263,7 +263,7 @@ std::pair<LocalTimeParameters, bool> ParseLocalTimeParameters(std::string_view l
if (!maybe_hour) {
throw temporal::InvalidArgumentException("Invalid hour in the string. {}", kSupportedTimeFormatsHelpMessage);
}
local_time_parameters.hours = *maybe_hour;
local_time_parameters.hour = *maybe_hour;
local_time_string.remove_prefix(2);
if (local_time_string.empty()) {
@ -276,7 +276,7 @@ std::pair<LocalTimeParameters, bool> ParseLocalTimeParameters(std::string_view l
if (!maybe_minute) {
throw temporal::InvalidArgumentException("Invalid minutes in the string. {}", kSupportedTimeFormatsHelpMessage);
}
local_time_parameters.minutes = *maybe_minute;
local_time_parameters.minute = *maybe_minute;
local_time_string.remove_prefix(2);
if (local_time_string.empty()) {
@ -289,7 +289,7 @@ std::pair<LocalTimeParameters, bool> ParseLocalTimeParameters(std::string_view l
if (!maybe_seconds) {
throw temporal::InvalidArgumentException("Invalid seconds in the string. {}", kSupportedTimeFormatsHelpMessage);
}
local_time_parameters.seconds = *maybe_seconds;
local_time_parameters.second = *maybe_seconds;
local_time_string.remove_prefix(2);
if (local_time_string.empty()) {
@ -306,7 +306,7 @@ std::pair<LocalTimeParameters, bool> ParseLocalTimeParameters(std::string_view l
throw temporal::InvalidArgumentException("Invalid milliseconds in the string. {}",
kSupportedTimeFormatsHelpMessage);
}
local_time_parameters.milliseconds = *maybe_milliseconds;
local_time_parameters.millisecond = *maybe_milliseconds;
local_time_string.remove_prefix(3);
if (local_time_string.empty()) {
@ -318,7 +318,7 @@ std::pair<LocalTimeParameters, bool> ParseLocalTimeParameters(std::string_view l
throw temporal::InvalidArgumentException("Invalid microseconds in the string. {}",
kSupportedTimeFormatsHelpMessage);
}
local_time_parameters.microseconds = *maybe_microseconds;
local_time_parameters.microsecond = *maybe_microseconds;
local_time_string.remove_prefix(3);
if (!local_time_string.empty()) {
@ -339,46 +339,46 @@ LocalTime::LocalTime(const int64_t microseconds) {
throw temporal::InvalidArgumentException("Invalid LocalTime specified in microseconds");
}
hours = parsed_hours;
minutes = GetAndSubtractDuration<std::chrono::minutes>(chrono_microseconds);
seconds = GetAndSubtractDuration<std::chrono::seconds>(chrono_microseconds);
milliseconds = GetAndSubtractDuration<std::chrono::milliseconds>(chrono_microseconds);
this->microseconds = chrono_microseconds.count();
hour = parsed_hours;
minute = GetAndSubtractDuration<std::chrono::minutes>(chrono_microseconds);
second = GetAndSubtractDuration<std::chrono::seconds>(chrono_microseconds);
millisecond = GetAndSubtractDuration<std::chrono::milliseconds>(chrono_microseconds);
microsecond = chrono_microseconds.count();
}
LocalTime::LocalTime(const LocalTimeParameters &local_time_parameters) {
if (!IsInBounds(0, 23, local_time_parameters.hours)) {
if (!IsInBounds(0, 23, local_time_parameters.hour)) {
throw temporal::InvalidArgumentException("Creating a LocalTime with invalid hour parameter.");
}
if (!IsInBounds(0, 59, local_time_parameters.minutes)) {
if (!IsInBounds(0, 59, local_time_parameters.minute)) {
throw temporal::InvalidArgumentException("Creating a LocalTime with invalid minutes parameter.");
}
// ISO 8601 supports leap seconds, but we ignore it for now to simplify the implementation
if (!IsInBounds(0, 59, local_time_parameters.seconds)) {
if (!IsInBounds(0, 59, local_time_parameters.second)) {
throw temporal::InvalidArgumentException("Creating a LocalTime with invalid seconds parameter.");
}
if (!IsInBounds(0, 999, local_time_parameters.milliseconds)) {
if (!IsInBounds(0, 999, local_time_parameters.millisecond)) {
throw temporal::InvalidArgumentException("Creating a LocalTime with invalid milliseconds parameter.");
}
if (!IsInBounds(0, 999, local_time_parameters.microseconds)) {
if (!IsInBounds(0, 999, local_time_parameters.microsecond)) {
throw temporal::InvalidArgumentException("Creating a LocalTime with invalid microseconds parameter.");
}
hours = local_time_parameters.hours;
minutes = local_time_parameters.minutes;
seconds = local_time_parameters.seconds;
milliseconds = local_time_parameters.milliseconds;
microseconds = local_time_parameters.microseconds;
hour = local_time_parameters.hour;
minute = local_time_parameters.minute;
second = local_time_parameters.second;
millisecond = local_time_parameters.millisecond;
microsecond = local_time_parameters.microsecond;
}
std::chrono::microseconds LocalTime::SumLocalTimeParts() const {
namespace chrono = std::chrono;
return chrono::hours{hours} + chrono::minutes{minutes} + chrono::seconds{seconds} +
chrono::milliseconds{milliseconds} + chrono::microseconds{microseconds};
return chrono::hours{hour} + chrono::minutes{minute} + chrono::seconds{second} + chrono::milliseconds{millisecond} +
chrono::microseconds{microsecond};
}
int64_t LocalTime::MicrosecondsSinceEpoch() const { return SumLocalTimeParts().count(); }
@ -390,11 +390,11 @@ int64_t LocalTime::NanosecondsSinceEpoch() const {
size_t LocalTimeHash::operator()(const LocalTime &local_time) const {
utils::HashCombine<uint64_t, uint64_t> hasher;
size_t result = hasher(0, local_time.hours);
result = hasher(result, local_time.minutes);
result = hasher(result, local_time.seconds);
result = hasher(result, local_time.milliseconds);
result = hasher(result, local_time.microseconds);
size_t result = hasher(0, local_time.hour);
result = hasher(result, local_time.minute);
result = hasher(result, local_time.second);
result = hasher(result, local_time.millisecond);
result = hasher(result, local_time.microsecond);
return result;
}
@ -486,17 +486,16 @@ int64_t LocalDateTime::MicrosecondsSinceEpoch() const {
int64_t LocalDateTime::SecondsSinceEpoch() const {
namespace chrono = std::chrono;
const auto to_sec = chrono::duration_cast<chrono::seconds>(DaysSinceEpoch(date.years, date.months, date.days));
const auto to_sec = chrono::duration_cast<chrono::seconds>(DaysSinceEpoch(date.year, date.month, date.day));
const auto local_time_seconds =
chrono::hours(local_time.hours) + chrono::minutes(local_time.minutes) + chrono::seconds(local_time.seconds);
chrono::hours(local_time.hour) + chrono::minutes(local_time.minute) + chrono::seconds(local_time.second);
return (to_sec + local_time_seconds).count();
}
int64_t LocalDateTime::SubSecondsAsNanoseconds() const {
namespace chrono = std::chrono;
const auto milli_as_nanos = chrono::duration_cast<chrono::nanoseconds>(chrono::milliseconds(local_time.milliseconds));
const auto micros_as_nanos =
chrono::duration_cast<chrono::nanoseconds>(chrono::microseconds(local_time.microseconds));
const auto milli_as_nanos = chrono::duration_cast<chrono::nanoseconds>(chrono::milliseconds(local_time.millisecond));
const auto micros_as_nanos = chrono::duration_cast<chrono::nanoseconds>(chrono::microseconds(local_time.microsecond));
return (milli_as_nanos + micros_as_nanos).count();
}
@ -566,7 +565,7 @@ std::optional<DurationParameters> TryParseDurationString(std::string_view string
};
const auto parse_duration_days_part = [&](auto date_string) {
if (!parse_and_assign(date_string, 'D', duration_parameters.days)) {
if (!parse_and_assign(date_string, 'D', duration_parameters.day)) {
return false;
}
@ -574,21 +573,21 @@ std::optional<DurationParameters> TryParseDurationString(std::string_view string
};
const auto parse_duration_time_part = [&](auto time_string) {
if (!parse_and_assign(time_string, 'H', duration_parameters.hours)) {
if (!parse_and_assign(time_string, 'H', duration_parameters.hour)) {
return false;
}
if (time_string.empty()) {
return true;
}
if (!parse_and_assign(time_string, 'M', duration_parameters.minutes)) {
if (!parse_and_assign(time_string, 'M', duration_parameters.minute)) {
return false;
}
if (time_string.empty()) {
return true;
}
if (!parse_and_assign(time_string, 'S', duration_parameters.seconds)) {
if (!parse_and_assign(time_string, 'S', duration_parameters.second)) {
return false;
}
@ -661,12 +660,12 @@ constexpr To CastChronoDouble(const double value) {
Duration::Duration(int64_t microseconds) { this->microseconds = microseconds; }
Duration::Duration(const DurationParameters &parameters) {
microseconds = (CastChronoDouble<std::chrono::days, std::chrono::microseconds>(parameters.days) +
CastChronoDouble<std::chrono::hours, std::chrono::microseconds>(parameters.hours) +
CastChronoDouble<std::chrono::minutes, std::chrono::microseconds>(parameters.minutes) +
CastChronoDouble<std::chrono::seconds, std::chrono::microseconds>(parameters.seconds) +
CastChronoDouble<std::chrono::milliseconds, std::chrono::microseconds>(parameters.milliseconds) +
CastChronoDouble<std::chrono::microseconds, std::chrono::microseconds>(parameters.microseconds))
microseconds = (CastChronoDouble<std::chrono::days, std::chrono::microseconds>(parameters.day) +
CastChronoDouble<std::chrono::hours, std::chrono::microseconds>(parameters.hour) +
CastChronoDouble<std::chrono::minutes, std::chrono::microseconds>(parameters.minute) +
CastChronoDouble<std::chrono::seconds, std::chrono::microseconds>(parameters.second) +
CastChronoDouble<std::chrono::milliseconds, std::chrono::microseconds>(parameters.millisecond) +
CastChronoDouble<std::chrono::microseconds, std::chrono::microseconds>(parameters.microsecond))
.count();
}

View File

@ -47,12 +47,12 @@ struct InvalidArgumentException : public utils::BasicException {
} // namespace temporal
struct DurationParameters {
double days{0};
double hours{0};
double minutes{0};
double seconds{0};
double milliseconds{0};
double microseconds{0};
double day{0};
double hour{0};
double minute{0};
double second{0};
double millisecond{0};
double microsecond{0};
};
DurationParameters ParseDurationParameters(std::string_view string);
@ -115,9 +115,9 @@ struct DurationHash {
};
struct DateParameters {
int64_t years{0};
int64_t months{1};
int64_t days{1};
int64_t year{0};
int64_t month{1};
int64_t day{1};
bool operator==(const DateParameters &) const = default;
};
@ -125,28 +125,28 @@ struct DateParameters {
// boolean indicates whether the parsed string was in extended format
std::pair<DateParameters, bool> ParseDateParameters(std::string_view date_string);
constexpr std::chrono::year_month_day ToChronoYMD(uint16_t years, uint8_t months, uint8_t days) {
constexpr std::chrono::year_month_day ToChronoYMD(uint16_t year, uint8_t month, uint8_t day) {
namespace chrono = std::chrono;
return chrono::year_month_day(chrono::year(years), chrono::month(months), chrono::day(days));
return chrono::year_month_day(chrono::year(year), chrono::month(month), chrono::day(day));
}
constexpr std::chrono::sys_days ToChronoSysDaysYMD(uint16_t years, uint8_t months, uint8_t days) {
return std::chrono::sys_days(ToChronoYMD(years, months, days));
constexpr std::chrono::sys_days ToChronoSysDaysYMD(uint16_t year, uint8_t month, uint8_t day) {
return std::chrono::sys_days(ToChronoYMD(year, month, day));
}
constexpr std::chrono::days DaysSinceEpoch(uint16_t years, uint8_t months, uint8_t days) {
return ToChronoSysDaysYMD(years, months, days).time_since_epoch();
constexpr std::chrono::days DaysSinceEpoch(uint16_t year, uint8_t month, uint8_t day) {
return ToChronoSysDaysYMD(year, month, day).time_since_epoch();
}
struct Date {
explicit Date() : Date{DateParameters{}} {}
// we assume we accepted date in microseconds which was normilized using the epoch time point
// we assume we accepted date in microseconds which was normalized using the epoch time point
explicit Date(int64_t microseconds);
explicit Date(const DateParameters &date_parameters);
friend std::ostream &operator<<(std::ostream &os, const Date &date) {
return os << fmt::format("{:0>2}-{:0>2}-{:0>2}", date.years, static_cast<int>(date.months),
static_cast<int>(date.days));
return os << fmt::format("{:0>2}-{:0>2}-{:0>2}", date.year, static_cast<int>(date.month),
static_cast<int>(date.day));
}
int64_t MicrosecondsSinceEpoch() const;
@ -166,17 +166,17 @@ struct Date {
friend Duration operator-(const Date &lhs, const Date &rhs) {
namespace chrono = std::chrono;
const auto lhs_days = utils::DaysSinceEpoch(lhs.years, lhs.months, lhs.days);
const auto rhs_days = utils::DaysSinceEpoch(rhs.years, rhs.months, rhs.days);
const auto lhs_days = utils::DaysSinceEpoch(lhs.year, lhs.month, lhs.day);
const auto rhs_days = utils::DaysSinceEpoch(rhs.year, rhs.month, rhs.day);
const auto days_elapsed = lhs_days - rhs_days;
return Duration(chrono::duration_cast<chrono::microseconds>(days_elapsed).count());
}
auto operator<=>(const Date &) const = default;
uint16_t years;
uint8_t months;
uint8_t days;
uint16_t year;
uint8_t month;
uint8_t day;
};
struct DateHash {
@ -184,11 +184,11 @@ struct DateHash {
};
struct LocalTimeParameters {
int64_t hours{0};
int64_t minutes{0};
int64_t seconds{0};
int64_t milliseconds{0};
int64_t microseconds{0};
int64_t hour{0};
int64_t minute{0};
int64_t second{0};
int64_t millisecond{0};
int64_t microsecond{0};
bool operator==(const LocalTimeParameters &) const = default;
};
@ -213,9 +213,9 @@ struct LocalTime {
namespace chrono = std::chrono;
using milli = chrono::milliseconds;
using micro = chrono::microseconds;
const auto subseconds = milli(lt.milliseconds) + micro(lt.microseconds);
return os << fmt::format("{:0>2}:{:0>2}:{:0>2}.{:0>6}", static_cast<int>(lt.hours), static_cast<int>(lt.minutes),
static_cast<int>(lt.seconds), subseconds.count());
const auto subseconds = milli(lt.millisecond) + micro(lt.microsecond);
return os << fmt::format("{:0>2}:{:0>2}:{:0>2}.{:0>6}", static_cast<int>(lt.hour), static_cast<int>(lt.minute),
static_cast<int>(lt.second), subseconds.count());
}
friend LocalTime operator+(const LocalTime &local_time, const Duration &dur) {
@ -246,11 +246,11 @@ struct LocalTime {
return lhs_dur - rhs_dur;
}
uint8_t hours;
uint8_t minutes;
uint8_t seconds;
uint16_t milliseconds;
uint16_t microseconds;
uint8_t hour;
uint8_t minute;
uint8_t second;
uint16_t millisecond;
uint16_t microsecond;
};
struct LocalTimeHash {

View File

@ -444,9 +444,9 @@ constexpr uint8_t Cast(T marker) {
}
void AssertThatDatesAreEqual(const utils::Date &d1, const utils::Date &d2) {
ASSERT_EQ(d1.days, d2.days);
ASSERT_EQ(d1.months, d2.months);
ASSERT_EQ(d1.years, d2.years);
ASSERT_EQ(d1.day, d2.day);
ASSERT_EQ(d1.month, d2.month);
ASSERT_EQ(d1.year, d2.year);
}
TEST_F(BoltDecoder, DateOld) {
@ -594,11 +594,11 @@ TEST_F(BoltDecoder, ArbitraryDuration) {
}
void AssertThatLocalTimeIsEqual(utils::LocalTime t1, utils::LocalTime t2) {
ASSERT_EQ(t1.hours, t2.hours);
ASSERT_EQ(t1.minutes, t2.minutes);
ASSERT_EQ(t1.seconds, t2.seconds);
ASSERT_EQ(t1.microseconds, t2.microseconds);
ASSERT_EQ(t1.milliseconds, t2.milliseconds);
ASSERT_EQ(t1.hour, t2.hour);
ASSERT_EQ(t1.minute, t2.minute);
ASSERT_EQ(t1.second, t2.second);
ASSERT_EQ(t1.microsecond, t2.microsecond);
ASSERT_EQ(t1.millisecond, t2.millisecond);
}
TEST_F(BoltDecoder, LocalTimeOneMicro) {

View File

@ -985,41 +985,41 @@ TEST_F(ExpressionEvaluatorPropertyLookup, Duration) {
const utils::Duration dur({10, 1, 30, 2, 22, 45});
frame[symbol] = TypedValue(dur);
const std::pair days = std::make_pair("days", dba.NameToProperty("days"));
const auto total_days = Value(days);
const std::pair day = std::make_pair("day", dba.NameToProperty("day"));
const auto total_days = Value(day);
EXPECT_TRUE(total_days.IsInt());
EXPECT_EQ(total_days.ValueInt(), 10);
const std::pair hours = std::make_pair("hours", dba.NameToProperty("hours"));
const auto total_hours = Value(hours);
const std::pair hour = std::make_pair("hour", dba.NameToProperty("hour"));
const auto total_hours = Value(hour);
EXPECT_TRUE(total_hours.IsInt());
EXPECT_EQ(total_hours.ValueInt(), 1);
const std::pair mins = std::make_pair("minutes", dba.NameToProperty("minutes"));
const auto total_mins = Value(mins);
const std::pair minute = std::make_pair("minute", dba.NameToProperty("minute"));
const auto total_mins = Value(minute);
EXPECT_TRUE(total_mins.IsInt());
EXPECT_EQ(total_mins.ValueInt(), 1 * 60 + 30);
const std::pair secs = std::make_pair("seconds", dba.NameToProperty("seconds"));
const auto total_secs = Value(secs);
const std::pair sec = std::make_pair("second", dba.NameToProperty("second"));
const auto total_secs = Value(sec);
EXPECT_TRUE(total_secs.IsInt());
const auto expected_secs = total_mins.ValueInt() * 60 + 2;
EXPECT_EQ(total_secs.ValueInt(), expected_secs);
const std::pair milli = std::make_pair("milliseconds", dba.NameToProperty("milliseconds"));
const std::pair milli = std::make_pair("millisecond", dba.NameToProperty("millisecond"));
const auto total_milli = Value(milli);
EXPECT_TRUE(total_milli.IsInt());
const auto expected_milli = total_secs.ValueInt() * 1000 + 22;
EXPECT_EQ(total_milli.ValueInt(), expected_milli);
const std::pair micro = std::make_pair("microseconds", dba.NameToProperty("microseconds"));
const std::pair micro = std::make_pair("microsecond", dba.NameToProperty("microsecond"));
const auto total_micros = Value(micro);
EXPECT_TRUE(total_micros.IsInt());
const auto expected_micros = expected_milli * 1000 + 45;
EXPECT_EQ(total_micros.ValueInt(), expected_micros);
const std::pair nano = std::make_pair("nanoseconds", dba.NameToProperty("nanoseconds"));
const std::pair nano = std::make_pair("nanosecond", dba.NameToProperty("nanosecond"));
const auto total_nano = Value(nano);
EXPECT_TRUE(total_nano.IsInt());
const auto expected_nano = expected_micros * 1000;
@ -1030,18 +1030,18 @@ TEST_F(ExpressionEvaluatorPropertyLookup, Date) {
const utils::Date date({1996, 11, 22});
frame[symbol] = TypedValue(date);
const std::pair years = std::make_pair("year", dba.NameToProperty("year"));
const auto y = Value(years);
const std::pair year = std::make_pair("year", dba.NameToProperty("year"));
const auto y = Value(year);
EXPECT_TRUE(y.IsInt());
EXPECT_EQ(y.ValueInt(), 1996);
const std::pair months = std::make_pair("month", dba.NameToProperty("month"));
const auto m = Value(months);
const std::pair month = std::make_pair("month", dba.NameToProperty("month"));
const auto m = Value(month);
EXPECT_TRUE(m.IsInt());
EXPECT_EQ(m.ValueInt(), 11);
const std::pair days = std::make_pair("day", dba.NameToProperty("day"));
const auto d = Value(days);
const std::pair day = std::make_pair("day", dba.NameToProperty("day"));
const auto d = Value(day);
EXPECT_TRUE(d.IsInt());
EXPECT_EQ(d.ValueInt(), 22);
}
@ -1060,17 +1060,17 @@ TEST_F(ExpressionEvaluatorPropertyLookup, LocalTime) {
EXPECT_TRUE(min.IsInt());
EXPECT_EQ(min.ValueInt(), 2);
const std::pair second = std::make_pair("seconds", dba.NameToProperty("seconds"));
const std::pair second = std::make_pair("second", dba.NameToProperty("second"));
const auto sec = Value(second);
EXPECT_TRUE(sec.IsInt());
EXPECT_EQ(sec.ValueInt(), 3);
const std::pair millis = std::make_pair("milliseconds", dba.NameToProperty("milliseconds"));
const std::pair millis = std::make_pair("millisecond", dba.NameToProperty("millisecond"));
const auto mil = Value(millis);
EXPECT_TRUE(mil.IsInt());
EXPECT_EQ(mil.ValueInt(), 11);
const std::pair micros = std::make_pair("microseconds", dba.NameToProperty("microseconds"));
const std::pair micros = std::make_pair("microsecond", dba.NameToProperty("microsecond"));
const auto mic = Value(micros);
EXPECT_TRUE(mic.IsInt());
EXPECT_EQ(mic.ValueInt(), 22);
@ -1080,18 +1080,18 @@ TEST_F(ExpressionEvaluatorPropertyLookup, LocalDateTime) {
const utils::LocalDateTime ldt({1993, 8, 6}, {2, 3, 4, 55, 40});
frame[symbol] = TypedValue(ldt);
const std::pair years = std::make_pair("year", dba.NameToProperty("year"));
const auto y = Value(years);
const std::pair year = std::make_pair("year", dba.NameToProperty("year"));
const auto y = Value(year);
EXPECT_TRUE(y.IsInt());
EXPECT_EQ(y.ValueInt(), 1993);
const std::pair months = std::make_pair("month", dba.NameToProperty("month"));
const auto m = Value(months);
const std::pair month = std::make_pair("month", dba.NameToProperty("month"));
const auto m = Value(month);
EXPECT_TRUE(m.IsInt());
EXPECT_EQ(m.ValueInt(), 8);
const std::pair days = std::make_pair("day", dba.NameToProperty("day"));
const auto d = Value(days);
const std::pair day = std::make_pair("day", dba.NameToProperty("day"));
const auto d = Value(day);
EXPECT_TRUE(d.IsInt());
EXPECT_EQ(d.ValueInt(), 6);
@ -1105,17 +1105,17 @@ TEST_F(ExpressionEvaluatorPropertyLookup, LocalDateTime) {
EXPECT_TRUE(min.IsInt());
EXPECT_EQ(min.ValueInt(), 3);
const std::pair second = std::make_pair("seconds", dba.NameToProperty("seconds"));
const std::pair second = std::make_pair("second", dba.NameToProperty("second"));
const auto sec = Value(second);
EXPECT_TRUE(sec.IsInt());
EXPECT_EQ(sec.ValueInt(), 4);
const std::pair millis = std::make_pair("milliseconds", dba.NameToProperty("milliseconds"));
const std::pair millis = std::make_pair("millisecond", dba.NameToProperty("millisecond"));
const auto mil = Value(millis);
EXPECT_TRUE(mil.IsInt());
EXPECT_EQ(mil.ValueInt(), 55);
const std::pair micros = std::make_pair("microseconds", dba.NameToProperty("microseconds"));
const std::pair micros = std::make_pair("microsecond", dba.NameToProperty("microsecond"));
const auto mic = Value(micros);
EXPECT_TRUE(mic.IsInt());
EXPECT_EQ(mic.ValueInt(), 40);

View File

@ -13,12 +13,12 @@
namespace {
std::string ToString(const utils::DateParameters &date_parameters) {
return fmt::format("{:04d}-{:02d}-{:02d}", date_parameters.years, date_parameters.months, date_parameters.days);
return fmt::format("{:04d}-{:02d}-{:02d}", date_parameters.year, date_parameters.month, date_parameters.day);
}
std::string ToString(const utils::LocalTimeParameters &local_time_parameters) {
return fmt::format("{:02}:{:02d}:{:02d}", local_time_parameters.hours, local_time_parameters.minutes,
local_time_parameters.seconds);
return fmt::format("{:02}:{:02d}:{:02d}", local_time_parameters.hour, local_time_parameters.minute,
local_time_parameters.second);
}
struct TestDateParameters {
@ -37,13 +37,18 @@ struct TestLocalTimeParameters {
bool should_throw;
};
constexpr std::array test_local_times{
TestLocalTimeParameters{{.hours = 24}, true}, TestLocalTimeParameters{{.hours = -1}, true},
TestLocalTimeParameters{{.minutes = -1}, true}, TestLocalTimeParameters{{.minutes = 60}, true},
TestLocalTimeParameters{{.seconds = -1}, true}, TestLocalTimeParameters{{.minutes = 60}, true},
TestLocalTimeParameters{{.milliseconds = -1}, true}, TestLocalTimeParameters{{.milliseconds = 1000}, true},
TestLocalTimeParameters{{.microseconds = -1}, true}, TestLocalTimeParameters{{.microseconds = 1000}, true},
TestLocalTimeParameters{{23, 59, 59, 999, 999}, false}, TestLocalTimeParameters{{0, 0, 0, 0, 0}, false}};
constexpr std::array test_local_times{TestLocalTimeParameters{{.hour = 24}, true},
TestLocalTimeParameters{{.hour = -1}, true},
TestLocalTimeParameters{{.minute = -1}, true},
TestLocalTimeParameters{{.minute = 60}, true},
TestLocalTimeParameters{{.second = -1}, true},
TestLocalTimeParameters{{.minute = 60}, true},
TestLocalTimeParameters{{.millisecond = -1}, true},
TestLocalTimeParameters{{.millisecond = 1000}, true},
TestLocalTimeParameters{{.microsecond = -1}, true},
TestLocalTimeParameters{{.microsecond = 1000}, true},
TestLocalTimeParameters{{23, 59, 59, 999, 999}, false},
TestLocalTimeParameters{{0, 0, 0, 0, 0}, false}};
} // namespace
TEST(TemporalTest, DateConstruction) {
@ -160,15 +165,15 @@ TEST(TemporalTest, LocalDateTimeMicrosecondsSinceEpochConversion) {
TEST(TemporalTest, DurationConversion) {
{
utils::Duration duration{{.minutes = 123.25}};
utils::Duration duration{{.minute = 123.25}};
const auto microseconds = duration.microseconds;
utils::LocalDateTime local_date_time{microseconds};
ASSERT_EQ(local_date_time.date.years, 1970);
ASSERT_EQ(local_date_time.date.months, 1);
ASSERT_EQ(local_date_time.date.days, 1);
ASSERT_EQ(local_date_time.local_time.hours, 2);
ASSERT_EQ(local_date_time.local_time.minutes, 3);
ASSERT_EQ(local_date_time.local_time.seconds, 15);
ASSERT_EQ(local_date_time.date.year, 1970);
ASSERT_EQ(local_date_time.date.month, 1);
ASSERT_EQ(local_date_time.date.day, 1);
ASSERT_EQ(local_date_time.local_time.hour, 2);
ASSERT_EQ(local_date_time.local_time.minute, 3);
ASSERT_EQ(local_date_time.local_time.second, 15);
};
}
@ -252,29 +257,29 @@ TEST(TemporalTest, LocalDateTimeParsing) {
}
void CheckDurationParameters(const auto &values, const auto &expected) {
ASSERT_EQ(values.days, expected.days);
ASSERT_EQ(values.hours, expected.hours);
ASSERT_EQ(values.minutes, expected.minutes);
ASSERT_EQ(values.seconds, expected.seconds);
ASSERT_EQ(values.milliseconds, expected.milliseconds);
ASSERT_EQ(values.microseconds, expected.microseconds);
ASSERT_EQ(values.day, expected.day);
ASSERT_EQ(values.hour, expected.hour);
ASSERT_EQ(values.minute, expected.minute);
ASSERT_EQ(values.second, expected.second);
ASSERT_EQ(values.millisecond, expected.millisecond);
ASSERT_EQ(values.microsecond, expected.microsecond);
}
TEST(TemporalTest, DurationParsing) {
ASSERT_THROW(utils::ParseDurationParameters("P12Y"), utils::BasicException);
ASSERT_THROW(utils::ParseDurationParameters("P12Y32DT2M"), utils::BasicException);
CheckDurationParameters(utils::ParseDurationParameters("PT26H"), utils::DurationParameters{.hours = 26});
CheckDurationParameters(utils::ParseDurationParameters("PT2M"), utils::DurationParameters{.minutes = 2.0});
CheckDurationParameters(utils::ParseDurationParameters("PT22S"), utils::DurationParameters{.seconds = 22});
CheckDurationParameters(utils::ParseDurationParameters("PT26H"), utils::DurationParameters{.hour = 26});
CheckDurationParameters(utils::ParseDurationParameters("PT2M"), utils::DurationParameters{.minute = 2.0});
CheckDurationParameters(utils::ParseDurationParameters("PT22S"), utils::DurationParameters{.second = 22});
CheckDurationParameters(utils::ParseDurationParameters("PT.33S"), utils::DurationParameters{.seconds = 0.33});
CheckDurationParameters(utils::ParseDurationParameters("PT.33S"), utils::DurationParameters{.second = 0.33});
CheckDurationParameters(utils::ParseDurationParameters("PT2M3S"),
utils::DurationParameters{.minutes = 2.0, .seconds = 3.0});
CheckDurationParameters(utils::ParseDurationParameters("PT2.5H"), utils::DurationParameters{.hours = 2.5});
utils::DurationParameters{.minute = 2.0, .second = 3.0});
CheckDurationParameters(utils::ParseDurationParameters("PT2.5H"), utils::DurationParameters{.hour = 2.5});
CheckDurationParameters(utils::ParseDurationParameters("P2DT2.5H"),
utils::DurationParameters{.days = 2.0, .hours = 2.5});
utils::DurationParameters{.day = 2.0, .hour = 2.5});
ASSERT_THROW(utils::ParseDurationParameters("P2M3S"), utils::BasicException);
ASSERT_THROW(utils::ParseDurationParameters("PTM3S"), utils::BasicException);
@ -439,16 +444,16 @@ TEST(TemporalTest, LocalTimeAndDurationAddition) {
const auto half_an_hour_before_midnight = utils::LocalTime({23, 30, 10});
{
const auto half_past_midnight = half_an_hour_before_midnight + utils::Duration({1, 1, 0, 0});
ASSERT_EQ(half_past_midnight, utils::LocalTime({.minutes = 30, .seconds = 10}));
ASSERT_EQ(half_past_midnight, utils::LocalTime({.minute = 30, .second = 10}));
}
const auto identity = half_an_hour_before_midnight + utils::Duration({.days = 1});
const auto identity = half_an_hour_before_midnight + utils::Duration({.day = 1});
ASSERT_EQ(identity, half_an_hour_before_midnight);
ASSERT_EQ(identity, half_an_hour_before_midnight + utils::Duration({.days = 1, .hours = 24}));
ASSERT_EQ(identity, half_an_hour_before_midnight + utils::Duration({.day = 1, .hour = 24}));
const auto an_hour_and_a_half_before_midnight = utils::LocalTime({22, 30, 10});
ASSERT_EQ(half_an_hour_before_midnight + utils::Duration({.hours = 23}), an_hour_and_a_half_before_midnight);
ASSERT_EQ(half_an_hour_before_midnight + utils::Duration({.hour = 23}), an_hour_and_a_half_before_midnight);
const auto minus_one_hour = utils::Duration({-10, -1, 0, 0, -20, -20});
const auto minus_one_hour_exact = utils::Duration({.days = -10, .hours = -1});
const auto minus_one_hour_exact = utils::Duration({.day = -10, .hour = -1});
{
const auto half_past_midnight = half_past_one + minus_one_hour;
ASSERT_EQ(half_past_midnight, utils::LocalTime({0, 30, 9, 979, 980}));
@ -484,41 +489,41 @@ TEST(TemporalTest, LocalTimeDeltaDuration) {
const auto half_past_one = utils::LocalTime({1, 30, 10});
const auto half_past_two = utils::LocalTime({2, 30, 10});
const auto an_hour_negative = half_past_one - half_past_two;
ASSERT_EQ(an_hour_negative, utils::Duration({.hours = -1}));
ASSERT_EQ(an_hour_negative, utils::Duration({.hour = -1}));
const auto an_hour = half_past_two - half_past_one;
ASSERT_EQ(an_hour, utils::Duration({.hours = 1}));
ASSERT_EQ(an_hour, utils::Duration({.hour = 1}));
}
TEST(TemporalTest, DateAddition) {
const auto unix_epoch = utils::Date({1970, 1, 1});
const auto one_day_after_unix_epoch = unix_epoch + utils::Duration({.days = 1});
const auto one_day_after_unix_epoch_symmetrical = utils::Duration({.days = 1}) + unix_epoch;
const auto one_day_after_unix_epoch = unix_epoch + utils::Duration({.day = 1});
const auto one_day_after_unix_epoch_symmetrical = utils::Duration({.day = 1}) + unix_epoch;
ASSERT_EQ(one_day_after_unix_epoch, utils::Date({1970, 1, 2}));
ASSERT_EQ(one_day_after_unix_epoch_symmetrical, one_day_after_unix_epoch);
const auto one_month_after_unix_epoch = unix_epoch + utils::Duration({.days = 31});
const auto one_month_after_unix_epoch = unix_epoch + utils::Duration({.day = 31});
ASSERT_EQ(one_month_after_unix_epoch, utils::Date({1970, 2, 1}));
const auto one_year_after_unix_epoch = unix_epoch + utils::Duration({.days = 365});
const auto one_year_after_unix_epoch = unix_epoch + utils::Duration({.day = 365});
ASSERT_EQ(one_year_after_unix_epoch, utils::Date({1971, 1, 1}));
const auto last_day_of_unix_epoch = one_year_after_unix_epoch + utils::Duration({.days = -1});
const auto last_day_of_unix_epoch = one_year_after_unix_epoch + utils::Duration({.day = -1});
ASSERT_EQ(last_day_of_unix_epoch, utils::Date({1970, 12, 31}));
const auto one_day_before_unix_epoch = unix_epoch + utils::Duration({.days = -1});
const auto one_day_before_unix_epoch = unix_epoch + utils::Duration({.day = -1});
ASSERT_EQ(one_day_before_unix_epoch, utils::Date({1969, 12, 31}));
ASSERT_EQ(last_day_of_unix_epoch + utils::Duration({.days = -31}), utils::Date({1970, 11, 30}));
ASSERT_EQ(last_day_of_unix_epoch + utils::Duration({.day = -31}), utils::Date({1970, 11, 30}));
ASSERT_THROW(unix_epoch + utils::Duration(std::numeric_limits<int64_t>::max()), utils::BasicException);
ASSERT_THROW(unix_epoch + utils::Duration(std::numeric_limits<int64_t>::min()), utils::BasicException);
}
TEST(TemporalTest, DateSubstraction) {
const auto day_after_unix_epoch = utils::Date({1970, 1, 2});
const auto unix_epoch = day_after_unix_epoch - utils::Duration({.days = 1});
const auto unix_epoch = day_after_unix_epoch - utils::Duration({.day = 1});
ASSERT_EQ(unix_epoch, utils::Date({1970, 1, 1}));
ASSERT_EQ(utils::Date({1971, 1, 1}) - utils::Duration({.days = 1}), utils::Date({1970, 12, 31}));
ASSERT_EQ(utils::Date({1971, 1, 1}) - utils::Duration({.days = -1}), utils::Date({1971, 1, 2}));
ASSERT_EQ(utils::Date({1971, 1, 1}) - utils::Duration({.day = 1}), utils::Date({1970, 12, 31}));
ASSERT_EQ(utils::Date({1971, 1, 1}) - utils::Duration({.day = -1}), utils::Date({1971, 1, 2}));
ASSERT_THROW(unix_epoch - utils::Duration(std::numeric_limits<int64_t>::max()), utils::BasicException);
ASSERT_THROW(unix_epoch - utils::Duration(std::numeric_limits<int64_t>::min()), utils::BasicException);
}
@ -526,25 +531,25 @@ TEST(TemporalTest, DateSubstraction) {
TEST(TemporalTest, DateDelta) {
const auto unix_epoch = utils::Date({1970, 1, 1});
const auto one_year_after_unix_epoch = utils::Date({1971, 1, 1});
ASSERT_EQ(one_year_after_unix_epoch - unix_epoch, utils::Duration({.days = 365}));
ASSERT_EQ(unix_epoch - one_year_after_unix_epoch, utils::Duration({.days = -365}));
ASSERT_EQ(one_year_after_unix_epoch - unix_epoch, utils::Duration({.day = 365}));
ASSERT_EQ(unix_epoch - one_year_after_unix_epoch, utils::Duration({.day = -365}));
}
TEST(TemporalTest, LocalDateTimeAdditionSubtraction) {
const auto unix_epoch = utils::LocalDateTime({1970, 1, 1}, {.hours = 12});
auto one_day_after_unix_epoch = unix_epoch + utils::Duration({.hours = 24});
auto one_day_after_unix_epoch_symmetrical = utils::Duration({.hours = 24}) + unix_epoch;
ASSERT_EQ(one_day_after_unix_epoch, utils::LocalDateTime({1970, 1, 2}, {.hours = 12}));
const auto unix_epoch = utils::LocalDateTime({1970, 1, 1}, {.hour = 12});
auto one_day_after_unix_epoch = unix_epoch + utils::Duration({.hour = 24});
auto one_day_after_unix_epoch_symmetrical = utils::Duration({.hour = 24}) + unix_epoch;
ASSERT_EQ(one_day_after_unix_epoch, utils::LocalDateTime({1970, 1, 2}, {.hour = 12}));
ASSERT_EQ(one_day_after_unix_epoch_symmetrical, one_day_after_unix_epoch);
const auto one_day_before_unix_epoch = utils::LocalDateTime({1969, 12, 31}, {23, 59, 59});
ASSERT_EQ(one_day_before_unix_epoch + utils::Duration({.seconds = 1}), utils::LocalDateTime({1970, 1, 1}, {}));
ASSERT_EQ(one_day_before_unix_epoch + utils::Duration({.second = 1}), utils::LocalDateTime({1970, 1, 1}, {}));
one_day_after_unix_epoch = unix_epoch + utils::Duration({.days = 1});
ASSERT_EQ(one_day_after_unix_epoch, utils::LocalDateTime({1970, 1, 2}, {.hours = 12}));
one_day_after_unix_epoch = unix_epoch + utils::Duration({.day = 1});
ASSERT_EQ(one_day_after_unix_epoch, utils::LocalDateTime({1970, 1, 2}, {.hour = 12}));
ASSERT_EQ(one_day_after_unix_epoch + utils::Duration({.days = -1}), unix_epoch);
ASSERT_EQ(one_day_after_unix_epoch - utils::Duration({.days = 1}), unix_epoch);
ASSERT_EQ(one_day_after_unix_epoch + utils::Duration({.day = -1}), unix_epoch);
ASSERT_EQ(one_day_after_unix_epoch - utils::Duration({.day = 1}), unix_epoch);
ASSERT_THROW(one_day_after_unix_epoch + utils::Duration(std::numeric_limits<int64_t>::max()), utils::BasicException);
ASSERT_THROW(one_day_after_unix_epoch + utils::Duration(std::numeric_limits<int64_t>::min()), utils::BasicException);
ASSERT_THROW(one_day_after_unix_epoch - utils::Duration(std::numeric_limits<int64_t>::max()), utils::BasicException);
@ -555,8 +560,8 @@ TEST(TemporalTest, LocalDateTimeDelta) {
const auto unix_epoch = utils::LocalDateTime({1970, 1, 1}, {1, 1, 1});
const auto one_year_after_unix_epoch = utils::LocalDateTime({1971, 2, 1}, {12, 1, 1});
const auto two_years_after_unix_epoch = utils::LocalDateTime({1972, 2, 1}, {1, 1, 1, 20, 34});
ASSERT_EQ(one_year_after_unix_epoch - unix_epoch, utils::Duration({.days = 396, .hours = 11}));
ASSERT_EQ(unix_epoch - one_year_after_unix_epoch, utils::Duration({.days = -396, .hours = -11}));
ASSERT_EQ(one_year_after_unix_epoch - unix_epoch, utils::Duration({.day = 396, .hour = 11}));
ASSERT_EQ(unix_epoch - one_year_after_unix_epoch, utils::Duration({.day = -396, .hour = -11}));
ASSERT_EQ(two_years_after_unix_epoch - unix_epoch,
utils::Duration({.days = 761, .milliseconds = 20, .microseconds = 34}));
utils::Duration({.day = 761, .millisecond = 20, .microsecond = 34}));
}