| /** |
| * Copyright 2011-2015 Quickstep Technologies LLC. |
| * Copyright 2015 Pivotal Software, Inc. |
| * |
| * Licensed under the Apache License, Version 2.0 (the "License"); |
| * you may not use this file except in compliance with the License. |
| * You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| **/ |
| |
| #ifndef QUICKSTEP_TYPES_DATE_BINARY_OPERATORS_HPP_ |
| #define QUICKSTEP_TYPES_DATE_BINARY_OPERATORS_HPP_ |
| |
| #include <ctime> |
| |
| #include "types/DatetimeLit.hpp" |
| #include "types/IntervalLit.hpp" |
| #include "types/port/gmtime_r.hpp" |
| #include "types/port/timegm.hpp" |
| |
| #include "glog/logging.h" |
| |
| namespace quickstep { |
| |
| /** \addtogroup Types |
| * @{ |
| */ |
| |
| // Month arithmetic clamps to the actual last day of a given month. |
| inline void ClampDayOfMonth(struct tm *timeinfo) { |
| DCHECK_LT(timeinfo->tm_mday, 32); |
| switch (timeinfo->tm_mon) { |
| case 1: { |
| const int days_in_february |
| = ((timeinfo->tm_year & 3) == 0 && ((timeinfo->tm_year % 25) != 0 |
| || ((timeinfo->tm_year + 1900) & 15) == 0)) |
| ? 29 : 28; |
| timeinfo->tm_mday = timeinfo->tm_mday > days_in_february |
| ? days_in_february : timeinfo->tm_mday; |
| return; |
| } |
| case 3: |
| case 5: |
| case 8: |
| case 10: { |
| timeinfo->tm_mday = timeinfo->tm_mday == 31 ? 30 : timeinfo->tm_mday; |
| return; |
| } |
| default: |
| return; |
| } |
| } |
| |
| // Overloaded operators for all date operations. |
| inline DatetimeLit operator+(const DatetimeLit &lhs, const DatetimeIntervalLit &rhs) { |
| DatetimeLit datetime; |
| datetime.ticks = lhs.ticks + rhs.interval_ticks; |
| return datetime; |
| } |
| |
| inline DatetimeLit operator+(const DatetimeIntervalLit &lhs, const DatetimeLit &rhs) { |
| DatetimeLit datetime; |
| datetime.ticks = lhs.interval_ticks + rhs.ticks; |
| return datetime; |
| } |
| |
| inline DatetimeLit operator+(const DatetimeLit &lhs, const YearMonthIntervalLit &rhs) { |
| std::time_t timestamp = lhs.epochTime(); |
| |
| struct tm timeinfo; |
| quickstep::gmtime_r(×tamp, &timeinfo); |
| |
| timeinfo.tm_year += rhs.months / 12; |
| timeinfo.tm_mon += rhs.months % 12; |
| |
| if (timeinfo.tm_mon > 11) { |
| timeinfo.tm_mon -= 12; |
| ++timeinfo.tm_year; |
| } |
| |
| ClampDayOfMonth(&timeinfo); |
| |
| DatetimeLit datetime(DatetimeLit::FromEpochTime(quickstep::timegm(&timeinfo))); |
| datetime.ticks += lhs.subseconds(); |
| return datetime; // Datetime in GMT. |
| } |
| |
| inline DatetimeLit operator+(const YearMonthIntervalLit &lhs, const DatetimeLit &rhs) { |
| return rhs + lhs; |
| } |
| |
| inline DatetimeIntervalLit operator+(const DatetimeIntervalLit &lhs, const DatetimeIntervalLit &rhs) { |
| DatetimeIntervalLit interval(lhs); |
| interval += rhs; |
| return interval; |
| } |
| |
| inline YearMonthIntervalLit operator+(const YearMonthIntervalLit &lhs, const YearMonthIntervalLit &rhs) { |
| YearMonthIntervalLit interval(lhs); |
| interval += rhs; |
| return interval; |
| } |
| |
| // NOTE(zuyu): The result type of the Subtract between two Datetimes |
| // is DatetimeInterval, instead of YearMonthInterval. |
| inline DatetimeIntervalLit operator-(const DatetimeLit &lhs, const DatetimeLit &rhs) { |
| DatetimeIntervalLit interval; |
| interval.interval_ticks = lhs.ticks - rhs.ticks; |
| return interval; |
| } |
| |
| inline DatetimeLit operator-(const DatetimeLit &lhs, const DatetimeIntervalLit &rhs) { |
| DatetimeLit datetime; |
| datetime.ticks = lhs.ticks - rhs.interval_ticks; |
| return datetime; |
| } |
| |
| inline DatetimeLit operator-(const DatetimeLit &lhs, const YearMonthIntervalLit &rhs) { |
| std::time_t timestamp = lhs.epochTime(); |
| struct tm timeinfo; |
| quickstep::gmtime_r(×tamp, &timeinfo); |
| |
| timeinfo.tm_year -= rhs.months / 12; |
| timeinfo.tm_mon -= rhs.months % 12; |
| |
| if (timeinfo.tm_mon < 0) { |
| --timeinfo.tm_year; |
| timeinfo.tm_mon += 12; |
| } |
| |
| ClampDayOfMonth(&timeinfo); |
| |
| DatetimeLit datetime(DatetimeLit::FromEpochTime(quickstep::timegm(&timeinfo))); |
| datetime.ticks += lhs.subseconds(); |
| return datetime; // Datetime in GMT. |
| } |
| |
| inline DatetimeIntervalLit operator-(const DatetimeIntervalLit &lhs, const DatetimeIntervalLit &rhs) { |
| DatetimeIntervalLit interval(lhs); |
| interval -= rhs; |
| return interval; |
| } |
| |
| inline YearMonthIntervalLit operator-(const YearMonthIntervalLit &lhs, const YearMonthIntervalLit &rhs) { |
| YearMonthIntervalLit interval(lhs); |
| interval -= rhs; |
| return interval; |
| } |
| |
| template <typename NumericCppType> |
| inline DatetimeIntervalLit operator*(const DatetimeIntervalLit &lhs, const NumericCppType &rhs) { |
| DatetimeIntervalLit interval(lhs); |
| interval *= rhs; |
| return interval; |
| } |
| |
| template <typename NumericCppType> |
| inline DatetimeIntervalLit operator*(const NumericCppType &lhs, const DatetimeIntervalLit &rhs) { |
| DatetimeIntervalLit interval(rhs); |
| interval *= lhs; |
| return interval; |
| } |
| |
| template <typename NumericCppType> |
| inline YearMonthIntervalLit operator*(const YearMonthIntervalLit &lhs, const NumericCppType &rhs) { |
| YearMonthIntervalLit interval(lhs); |
| interval *= rhs; |
| return interval; |
| } |
| |
| template <typename NumericCppType> |
| inline YearMonthIntervalLit operator*(const NumericCppType &lhs, const YearMonthIntervalLit &rhs) { |
| YearMonthIntervalLit interval(rhs); |
| interval *= lhs; |
| return interval; |
| } |
| |
| template <typename NumericCppType> |
| inline DatetimeIntervalLit operator/(const DatetimeIntervalLit &lhs, const NumericCppType &rhs) { |
| DatetimeIntervalLit interval(lhs); |
| interval /= rhs; |
| return interval; |
| } |
| |
| template <typename NumericCppType> |
| inline YearMonthIntervalLit operator/(const YearMonthIntervalLit &lhs, const NumericCppType &rhs) { |
| YearMonthIntervalLit interval(lhs); |
| interval /= rhs; |
| return interval; |
| } |
| |
| /** @} */ |
| |
| } // namespace quickstep |
| |
| #endif // QUICKSTEP_TYPES_DATE_BINARY_OPERATORS_HPP_ |