* This file is part of the oGRAC project.
* Copyright (c) 2024 Huawei Technologies Co.,Ltd.
*
* oGRAC is licensed under Mulan PSL v2.
* You can use this software according to the terms and conditions of the Mulan PSL v2.
* You may obtain a copy of Mulan PSL v2 at:
*
* http://license.coscl.org.cn/MulanPSL2
*
* THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
* EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
* MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
* See the Mulan PSL v2 for more details.
* -------------------------------------------------------------------------
*
* cm_date.h
*
*
* IDENTIFICATION
* src/common/cm_date.h
*
* -------------------------------------------------------------------------
*/
#ifndef __CM_DATE_H_
#define __CM_DATE_H_
#include "cm_text.h"
#include "cm_timezone.h"
#include <time.h>
#ifndef WIN32
#include <sys/time.h>
#else
#include <Winsock2.h>
#endif
#include <math.h>
#ifdef __cplusplus
extern "C" {
#endif
* The date type is represented by a 64-bit signed integer. The minimum unit
* is 1 microsecond. This indicates the precision can reach up to 6 digits after
* the decimal point.
*/
typedef int64 date_t;
* seconds: '2019-01-01 00:00:00'UTC since Epoch ('1970-01-01 00:00:00' UTC)
*/
#define CM_GTS_BASETIME 1546300800
* Set the minimal and maximal years that are supported by this database system.
* We set the BASELINE DATATIME by 2000-01-01 00:00:00.000000000, which corresponds
* to the value (date_t)0. For practice, CM_MIN_YEAR and CM_MAX_YEAR are used to
* restrict the year into a representable range. Here, we thus the `CM_MIN_YEAR`
* should be greater than 1707 (= BASELINE DATATIME - 584.54/2), and the `CM_MAX_YEAR`
* should be less than 2292 (= BASELINE DATATIME + 584.54/2).
* **NOTE: ** The YEAR is not allowed to set back to BC, that is, the YEAR must be
* greater than 0, since this program does not consider the chronology before BC yet.
* `CM_MAX_YEAR = CM_MIN_YEAR + maximal allowed range`
*/
#define CM_BASELINE_YEAY 2000
#define CM_MIN_YEAR 1
#define CM_MAX_YEAR 9999
#define CM_MIN_UTC 0
#define CM_MAX_UTC 2147483647.999999
#define CM_BASELINE_DAY ((int32)730120)
* `CM_MIN_DATE` is the minimal date, corresponding to the date `CM_MIN_YEAR-01-01 00:00:00.000000`
* `CM_MAX_DATE` is the maximal date, corresponding to the date `CM_MAX_YEAR-12-31 23:59:59.999999`
*/
#define CM_MIN_DATETIME ((date_t)-63082281600000000LL)
#define CM_MAX_DATETIME ((date_t)252455615999999999LL)
#define CM_ALL_ZERO_DATETIME ((date_t)-63113904000000000LL)
#define CM_MIN_DATE ((int32)-730119)
#define CM_MAX_DATE ((int32)2921940)
#define CM_ALL_ZERO_DATE ((int32)-730485)
#define CM_IS_VALID_YEAR(year) ((year) >= CM_MIN_YEAR && (year) <= CM_MAX_YEAR)
#define CM_IS_VALID_MONTH(mon) ((mon) >= 1 && (mon) <= 12)
#define CM_IS_VALID_DAY(day) ((day) >= 1 && (day) <= 31)
#define CM_IS_VALID_HOUR(hour) ((hour) >= 0 && (hour) <= 23)
#define CM_IS_VALID_MINUTE(min) ((min) >= 0 && (min) <= 59)
#define CM_IS_VALID_SECOND(sec) ((sec) >= 0 && (sec) <= 59)
#define CM_IS_VALID_FRAC_SEC(fsec) ((fsec) >= 0 && (fsec) <= 999999999)
#define CM_IS_VALID_DATE(d) (((d) == CM_ALL_ZERO_DATE || (d) >= CM_MIN_DATE) && (d) < CM_MAX_DATE)
#define CM_IS_VALID_TIMESTAMP(t) (((t) >= CM_MIN_DATETIME && (t) <= CM_MAX_DATETIME) || (t) == CM_ALL_ZERO_DATETIME)
#define SECONDS_PER_DAY 86400U
#define SECONDS_PER_HOUR 3600U
#define SECONDS_PER_MIN 60U
#define MILLISECS_PER_SECOND 1000U
#define MICROSECS_PER_MILLISEC 1000U
#define MICROSECS_PER_SECOND 1000000U
#define MICROSECS_PER_MIN 60000000U
#define NANOSECS_PER_MICROSEC 1000U
#define NANOSECS_PER_MILLISEC 1000000U
#define NANOSECS_PER_SECOND 1000000000U
#define MICROSECS_PER_SECOND_LL 1000000LL
#define NANOSECS_PER_SECOND_LL 1000000000ULL
#define DATETIMEF_INT_OFS 0x8000000000LL
#define DATETIME_MAX_DECIMALS 6
#define TIMEF_INT_OFS 0x800000LL
#define TIMEF_OFS 0x800000000000LL
#define DAYS_PER_WEEK 7U
#define UNITS_PER_DAY 86400000000LL
#define CM_UNIX_EPOCH (-946684800000000LL)
#define CM_BASE_8 8
#define CM_BASE_16 16
#define CM_BASE_24 24
#define CM_BASE_32 32
#define CM_BYTE_0 0
#define CM_BYTE_1 1
#define CM_BYTE_2 2
#define CM_BYTE_3 3
#define CM_BYTE_4 4
#define CM_BYTE_5 5
#define CM_BYTE_8 8
#define CM_DATE_PRE_0 0
#define CM_DATE_PRE_1 1
#define CM_DATE_PRE_2 2
#define CM_DATE_PRE_3 3
#define CM_DATE_PRE_4 4
#define CM_DATE_PRE_5 5
#define CM_DATE_PRE_6 6
#define CM_128_BITS_MASK 128
#define CM_255_BITS_MASK 255U
#define DT_ENCODE_2 2
#define DT_ENCODE_3 3
#define DT_ENCODE_5 5
#define DT_ENCODE_6 6
#define DT_ENCODE_10 10
#define DT_ENCODE_12 12
#define DT_ENCODE_13 13
#define DT_ENCODE_16 16
#define DT_ENCODE_17 17
#define DT_ENCODE_24 24
#define DT_ENCODE_32 32
#define CM_4_POWER_OF_10 10000
#define CM_2_POWER_OF_10 100
#define TEXT_LEN 3
#define DATE_MIN_LEN 3
#define HOUR_0 0
#define HOUR_12 12
#define DAY_FIELD_INDEX 2
#define DAY_MIN_VALUE 1
#define DAY_MAX_VALUE 31
#define CM_IS_DATETIME_ADDTION_OVERFLOW(dt, val, res) \
(!((val) >= 0 && (res) <= CM_MAX_DATETIME && (res) >= (dt)) && \
!((val) < 0 && ((res) >= CM_MIN_DATETIME || (res) == CM_ALL_ZERO_DATETIME) && (res) <= (dt)))
#define OG_SET_ERROR_DATETIME_OVERFLOW() \
OG_THROW_ERROR(ERR_TYPE_DATETIME_OVERFLOW, CM_MIN_YEAR, CM_MAX_YEAR)
#define OG_SET_ERROR_TIMESTAMP_OVERFLOW() \
OG_THROW_ERROR(ERR_TYPE_TIMESTAMP_OVERFLOW, CM_MIN_YEAR, CM_MAX_YEAR)
extern const uint64 powers_of_10[20];
* \brief A safe methods to calculate the addition between DATETIME TYPE and
* numerical types. It can avoid the overflow/underflow.
*
*/
static inline status_t cm_date_add_days(date_t dt, double day, date_t *res_dt)
{
date_t new_dt = dt + (date_t)round((double)UNITS_PER_DAY * day);
if (CM_IS_DATETIME_ADDTION_OVERFLOW(dt, day, new_dt)) {
OG_SET_ERROR_DATETIME_OVERFLOW();
return OG_ERROR;
}
*res_dt = new_dt;
return OG_SUCCESS;
}
static inline status_t cm_date_add_seconds(date_t dt, uint64 second, date_t *res_dt)
{
date_t new_dt = dt + (date_t)(MICROSECS_PER_SECOND * second);
if (CM_IS_DATETIME_ADDTION_OVERFLOW(dt, second, new_dt)) {
OG_SET_ERROR_DATETIME_OVERFLOW();
return OG_ERROR;
}
*res_dt = new_dt;
return OG_SUCCESS;
}
static inline status_t cm_date_sub_days(date_t dt, double day, date_t *res_dt)
{
return cm_date_add_days(dt, -day, res_dt);
}
static inline int32 cm_date_diff_days(date_t dt1, date_t dt2)
{
return (int32)((dt1 - dt2) / UNITS_PER_DAY);
}
#pragma pack(4)
typedef struct st_date_detail {
uint16 year;
uint8 mon;
uint8 day;
int32 hour;
uint8 min;
uint8 sec;
uint16 millisec;
uint16 microsec;
uint16 nanosec;
timezone_info_t tz_offset;
bool8 neg;
bool8 is_pm;
} date_detail_t;
#pragma pack()
typedef date_t timestamp_t;
#pragma pack(4)
typedef struct st_timestamp_tz {
timestamp_t tstamp;
timezone_info_t tz_offset;
int16 unused;
} timestamp_tz_t;
typedef date_t timestamp_ltz_t;
typedef struct st_date_detail_ex {
bool32 is_am;
uint32 seconds;
char ad;
uint8 week;
uint8 quarter;
uint8 day_of_week;
uint16 day_of_year;
char reserve[2];
} date_detail_ex_t;
#pragma pack()
static inline status_t cm_tstamp_add_days(timestamp_t ts, double day, date_t *res_ts)
{
return cm_date_add_days(ts, day, res_ts);
}
static inline status_t cm_tstamp_sub_days(timestamp_t ts, double day, date_t *res_ts)
{
return cm_tstamp_add_days(ts, -day, res_ts);
}
typedef enum en_format_id {
FMT_AM_INDICATOR = 100,
FMT_PM_INDICATOR = 101,
FMT_SPACE = 102,
FMT_MINUS = 103,
FMT_SLASH = 104,
FMT_BACK_SLASH = 105,
FMT_COMMA = 106,
FMT_DOT = 107,
FMT_SEMI_COLON = 108,
FMT_COLON = 109,
FMT_X = 110,
FMT_AM = 111,
FMT_PM = 112,
FMT_A_M = 113,
FMT_P_M = 114,
FMT_AM_DOT = 115,
FMT_PM_DOT = 116,
FMT_CENTURY = 201,
FMT_DAY_OF_WEEK = 202,
FMT_DAY_NAME = 203,
FMT_DAY_ABBR_NAME = 204,
FMT_DAY_OF_MONTH = 205,
FMT_DAY_OF_YEAR = 206,
FMT_FRAC_SECOND1 = 207,
FMT_FRAC_SECOND2 = 208,
FMT_FRAC_SECOND3 = 209,
FMT_FRAC_SECOND4 = 210,
FMT_FRAC_SECOND5 = 211,
FMT_FRAC_SECOND6 = 212,
FMT_FRAC_SECOND7 = 213,
FMT_FRAC_SECOND8 = 214,
FMT_FRAC_SECOND9 = 215,
FMT_FRAC_SEC_VAR_LEN = 250,
FMT_DQ_TEXT = 313,
FMT_MINUTE = 314,
FMT_MONTH = 315,
FMT_MONTH_ABBR_NAME = 316,
FMT_MONTH_NAME = 317,
FMT_QUARTER = 318,
FMT_SECOND = 319,
FMT_SECOND_PASS = 320,
FMT_WEEK_OF_YEAR = 321,
FMT_WEEK_OF_MONTH = 322,
* not be changed */
FMT_YEAR1 = 323,
FMT_YEAR2 = 324,
FMT_YEAR3 = 325,
FMT_YEAR4 = 326,
FMT_HOUR_OF_DAY12 = 328,
FMT_HOUR_OF_DAY24 = 329,
FMT_TZ_HOUR = 330,
FMT_TZ_MINUTE = 331,
FMT_MONTH_RM = 332
} format_id_t;
typedef struct en_format_item {
text_t name;
format_id_t id;
uint32 fmask;
int8 placer;
bool8 reversible;
bool8 dt_used;
} format_item_t;
typedef struct st_date_parse_params {
const text_t *text;
const text_t *fmt;
const text_t *nls;
bool32 is_date_fmt;
} date_parse_params_t;
#define MILL_SECOND1 (date_t)((double)1 / (double)86400000.0)
#define IS_LEAP_YEAR(year) (((year) % 4 == 0) && (((year) % 100 != 0) || ((year) % 400 == 0)) ? 1 : 0)
#define DAY2SECONDS(days) (days) * 24 * 3600;
extern uint16 g_month_days[2][12];
#define CM_MONTH_DAYS(year, mon) (g_month_days[IS_LEAP_YEAR(year)][(mon) - 1])
#define cm_check_special_char(text) \
do { \
if (*((text)->str) == '-' || *((text)->str) == ',' || \
*((text)->str) == '.' || *((text)->str) == ';' || \
*((text)->str) == ':' || *((text)->str) == '/') { \
--((text)->len); \
++((text)->str); \
} \
} while (0)
#define cm_int2_to_binary(ptr, i) \
do { \
uint temp = (uint)(i); \
((uchar *)(ptr))[1] = (uchar)(temp); \
((uchar *)(ptr))[0] = (uchar)(temp >> 8); \
} while (0)
#define cm_int3_to_binary(ptr, i) \
do { \
ulong temp = (ulong)(i); \
((uchar *)(ptr))[2] = (uchar)(temp); \
((uchar *)(ptr))[1] = (uchar)(temp >> 8); \
((uchar *)(ptr))[0] = (uchar)(temp >> 16); \
} while (0)
#define cm_int5_to_binary(ptr, i) \
do { \
ulong temp = (ulong)(i); \
ulong temp2 = (ulong)((i) >> 32); \
((uchar *)(ptr))[4] = (uchar)(temp); \
((uchar *)(ptr))[3] = (uchar)(temp >> 8); \
((uchar *)(ptr))[2] = (uchar)(temp >> 16); \
((uchar *)(ptr))[1] = (uchar)(temp >> 24); \
((uchar *)(ptr))[0] = (uchar)(temp2); \
} while (0)
#define cm_int6tobinary(ptr, i) \
do { \
ulong temp = (ulong)(i); \
ulong temp2 = (ulong)((i) >> 32); \
((uchar *)(ptr))[5] = (uchar)(temp); \
((uchar *)(ptr))[4] = (uchar)(temp >> 8); \
((uchar *)(ptr))[3] = (uchar)(temp >> 16); \
((uchar *)(ptr))[2] = (uchar)(temp >> 24); \
((uchar *)(ptr))[1] = (uchar)(temp2); \
((uchar *)(ptr))[0] = (uchar)(temp2 >> 8); \
} while (0)
#define cm_1_zero_ending(ptr) \
do { \
((uchar *)(ptr))[7] = (uchar)(0); \
} while (0)
#define cm_2_zero_ending(ptr) \
do { \
((uchar *)(ptr))[6] = (uchar)(0); \
((uchar *)(ptr))[7] = (uchar)(0); \
} while (0)
#define cm_3_zero_ending(ptr) \
do { \
((uchar *)(ptr))[5] = (uchar)(0); \
((uchar *)(ptr))[6] = (uchar)(0); \
((uchar *)(ptr))[7] = (uchar)(0); \
} while (0)
#define cm_4_zero_ending(ptr) \
do { \
((uchar *)(ptr))[4] = (uchar)(0); \
((uchar *)(ptr))[5] = (uchar)(0); \
((uchar *)(ptr))[6] = (uchar)(0); \
((uchar *)(ptr))[7] = (uchar)(0); \
} while (0)
#define cm_5_zero_ending(ptr) \
do { \
((uchar *)(ptr))[3] = (uchar)(0); \
((uchar *)(ptr))[4] = (uchar)(0); \
((uchar *)(ptr))[5] = (uchar)(0); \
((uchar *)(ptr))[6] = (uchar)(0); \
((uchar *)(ptr))[7] = (uchar)(0); \
} while (0)
static inline int32 cm_compare_date(date_t date1, date_t date2)
{
int64 diff = date1 - date2;
return diff > 0 ? 1 : (diff < 0 ? -1 : 0);
}
date_t cm_now(void);
date_t cm_utc_now(void);
date_t cm_date_now(void);
date_t cm_monotonic_now(void);
status_t cm_adjust_timestamp(timestamp_t *ts, int32 precision);
status_t cm_adjust_timestamp_tz(timestamp_tz_t *tstz, int32 precision);
status_t cm_text2date(const text_t *text, const text_t *fmt, date_t *date);
status_t cm_str2time(char *date, const text_t *fmt, time_t *time_stamp);
status_t cm_check_tstz_is_valid(timestamp_tz_t *tstz);
status_t cm_text2timestamp_tz(const text_t *text, const text_t *fmt, timezone_info_t default_tz, timestamp_tz_t *tstz);
status_t cm_text2date_fixed(const text_t *text, const text_t *fmt, date_t *date,
timezone_info_t *tz_offset, bool32 is_date_fmt);
status_t cm_text2date_fixed_nls(const date_parse_params_t *params, date_t *date,
timezone_info_t *tz_offset);
status_t cm_fetch_date_field(text_t *text, uint32 minval, uint32 maxval, char spilt_char, uint32 *field_val);
status_t cm_text2date_def(const text_t *text, date_t *date);
status_t cm_text2timestamp_def(const text_t *text, date_t *date);
status_t cm_text2date_flex(const text_t *text, date_t *date);
bool32 cm_str2week(text_t *value, uint8 *week);
time_t cm_current_time(void);
time_t cm_date2time(date_t date);
date_t cm_timestamp2date(date_t date_input);
status_t cm_verify_date_fmt(const text_t *fmt);
status_t cm_verify_timestamp_fmt(const text_t *fmt);
status_t cm_date2text_ex(date_t date, text_t *fmt, uint32 precision, text_t *text, uint32 max_len);
status_t cm_timestamp2text_ex(timestamp_t ts, text_t *fmt, uint32 precision, text_t *text,
uint32 max_len);
status_t cm_timestamp_tz2text_ex(timestamp_tz_t *tstz, text_t *fmt, uint32 precision, text_t *text,
uint32 max_len);
int64 cm_get_unix_timestamp(timestamp_t ts, int64 time_zone_offset);
int32 cm_tstz_cmp(timestamp_tz_t *tstz1, timestamp_tz_t *tstz2);
int64 cm_tstz_sub(timestamp_tz_t *tstz1, timestamp_tz_t *tstz2);
void cm_datetime_int_to_binary(int64 input, uchar *ptr, int32 precision);
void cm_time_int_to_binary(int64 input, uchar *ptr, int32 precision);
static inline status_t cm_date2str_ex(date_t date, text_t *fmt_text, char *str, uint32 max_len)
{
text_t date_text;
date_text.str = str;
date_text.len = 0;
return cm_date2text_ex(date, fmt_text, 0, &date_text, max_len);
}
static inline int32 cm_ptr3_to_sint_little_endian(const uchar *ptr)
{
return (int32)((ptr[CM_BYTE_0] & CM_128_BITS_MASK) ? ((CM_255_BITS_MASK << CM_BASE_24) |
((uint32)(ptr[CM_BYTE_0]) << CM_BASE_16) | ((uint32)(ptr[CM_BYTE_1]) << CM_BASE_8) | ((uint32)ptr[CM_BYTE_2])) :
(((uint32)(ptr[CM_BYTE_0]) << CM_BASE_16) |
((uint32)(ptr[CM_BYTE_1]) << CM_BASE_8) | ((uint32)(ptr[CM_BYTE_2]))));
}
static inline uint32 cm_ptr3_to_uint_big_endian(const uchar *ptr)
{
return (uint32)(((uint32)(ptr[CM_BYTE_0])) + (((uint32)(ptr[CM_BYTE_1])) << CM_BASE_8) +
(((uint32)(ptr[CM_BYTE_2])) << CM_BASE_16));
}
static inline uint64 cm_ptr5_to_uint_little_endian(const uchar *ptr)
{
return (uint64)((uint32)ptr[CM_BYTE_4] + ((uint32)ptr[CM_BYTE_3] << CM_BASE_8) +
((uint32)ptr[CM_BYTE_2] << CM_BASE_16) + ((uint32)ptr[CM_BYTE_1] << CM_BASE_24)) +
((uint64)ptr[CM_BYTE_0] << CM_BASE_32);
}
static inline uint64 cm_ptr6_to_uint_little_endian(const uchar *ptr)
{
return (uint64)((uint32)ptr[CM_BYTE_5] + ((uint32)ptr[CM_BYTE_4] << CM_BASE_8) +
((uint32)ptr[CM_BYTE_3] << CM_BASE_16) + ((uint32)ptr[CM_BYTE_2] << CM_BASE_24)) +
(((uint64)((uint32)ptr[CM_BYTE_1] + ((uint32)ptr[CM_BYTE_0] << CM_BASE_8))) << CM_BASE_32);
}
static inline uint32 cm_cnvrt_date_from_binary_to_uint(const uchar *ptr)
{
return cm_ptr3_to_uint_big_endian(ptr);
}
static inline int64 cm_cnvrt_time_from_binary_to_int(const uchar *ptr)
{
return ((int64)(cm_ptr6_to_uint_little_endian(ptr))) - TIMEF_OFS;
}
static int64 cm_pack_time_to_int64(int64 intpart, int64 fracpart)
{
cm_assert(abs(fracpart) <= 0xffffffLL);
return ((uint64)(intpart) << CM_BASE_24) + fracpart;
}
static inline int64 cm_cnvrt_datetime_from_binary_to_int(const uchar *ptr)
{
int64 intpart = cm_ptr5_to_uint_little_endian(ptr) - DATETIMEF_INT_OFS;
int32 fracpart = cm_ptr3_to_sint_little_endian(ptr + OG_DATETIME_PRECISION_5);
return cm_pack_time_to_int64(intpart, fracpart);
}
static inline int64 cm_get_time_int_part_from_int64(int64 input)
{
return ((uint64)input >> CM_BASE_24);
}
static inline int64 cm_get_time_frac_part_from_int64(int64 input)
{
return (input % (1LL << CM_BASE_24));
}
static inline status_t cm_timestamp2str_ex(timestamp_t ts, text_t *fmt_text, uint32 precision, char *str,
uint32 max_len)
{
text_t tmstamp_text;
tmstamp_text.str = str;
tmstamp_text.len = 0;
return cm_timestamp2text_ex(ts, fmt_text, precision, &tmstamp_text, max_len);
}
static inline status_t cm_timestamp_tz2str_ex(timestamp_tz_t *tstz, text_t *fmt_text, uint32 precision, char *str,
uint32 max_len)
{
text_t tmstamp_text;
tmstamp_text.str = str;
tmstamp_text.len = 0;
return cm_timestamp_tz2text_ex(tstz, fmt_text, precision, &tmstamp_text, max_len);
}
status_t cm_time2text(time_t time, text_t *fmt, text_t *text, uint32 max_len);
status_t cm_time2str(time_t time, const char *fmt, char *str, uint32 str_max_size);
date_t cm_time2date(time_t time);
void cm_now_detail(date_detail_t *detail);
void cm_decode_date(date_t date_input, date_detail_t *detail);
void cm_decode_time(time_t time, date_detail_t *detail);
static inline bool32 cm_is_all_zero_time(const date_detail_t *datetime)
{
if (datetime->year == 0 && datetime->mon == 0 && datetime->day == 0 && datetime->hour == 0 && datetime->min == 0 &&
datetime->sec == 0 && datetime->millisec == 0 && datetime->microsec == 0 && datetime->nanosec == 0) {
return OG_TRUE;
}
return OG_FALSE;
}
* 10 nanoseconds as the minimum unit, that is, 1 = 10 nanoseconds. */
date_t cm_encode_date(const date_detail_t *detail);
void cm_decode_ora_date(date_t date, uint8 *ora_date);
date_t cm_encode_ora_date(uint8 *ora_date);
time_t cm_encode_time(date_detail_t *detail);
void cm_cnvrt_datetime_from_int_to_date_detail(int64 input, date_detail_t *detail);
void cm_cnvrt_time_from_int_to_date_detail(int64 input, date_detail_t *detail);
static inline status_t cm_date2text(date_t date, text_t *fmt, text_t *text, uint32 max_len)
{
return cm_date2text_ex(date, fmt, OG_MAX_DATETIME_PRECISION, text, max_len);
}
static inline status_t cm_date2str(date_t date, const char *fmt, char *str, uint32 max_len)
{
text_t fmt_text;
cm_str2text((char *)fmt, &fmt_text);
return cm_date2str_ex(date, &fmt_text, str, max_len);
}
static inline status_t cm_timestamp2text(timestamp_t ts, text_t *fmt, text_t *text, uint32 max_len)
{
return cm_timestamp2text_ex(ts, fmt, OG_MAX_DATETIME_PRECISION, text, max_len);
}
static inline status_t cm_timestamp2text_prec(timestamp_t ts, text_t *fmt, text_t *text, uint32 max_len,
uint8 temestamp_prec)
{
return cm_timestamp2text_ex(ts, fmt, (uint32)temestamp_prec, text, max_len);
}
static inline status_t cm_timestamp2str(timestamp_t ts, const char *fmt, char *str, uint32 max_len)
{
text_t fmt_text;
cm_str2text((char *)fmt, &fmt_text);
return cm_timestamp2str_ex(ts, &fmt_text, OG_MAX_DATETIME_PRECISION, str, max_len);
}
static inline status_t cm_timestamp_tz2text(timestamp_tz_t *tstz, text_t *fmt, text_t *text,
uint32 max_len)
{
return cm_timestamp_tz2text_ex(tstz, fmt, OG_MAX_DATETIME_PRECISION, text, max_len);
}
static inline status_t cm_timestamp_tz2text_prec(timestamp_tz_t *tstz, text_t *fmt, text_t *text,
uint32 max_len, uint8 timestamp_prec)
{
return cm_timestamp_tz2text_ex(tstz, fmt, (uint32)timestamp_prec, text, max_len);
}
static inline status_t cm_timestamp_tz2str(timestamp_tz_t *tstz, const char *fmt, char *str, uint32 max_len)
{
text_t fmt_text;
cm_str2text((char *)fmt, &fmt_text);
return cm_timestamp_tz2str_ex(tstz, &fmt_text, OG_MAX_DATETIME_PRECISION, str, max_len);
}
static inline date_t cm_adjust_date(date_t date)
{
return date / MICROSECS_PER_SECOND * MICROSECS_PER_SECOND;
}
* this function is used to adjust time&date from src_tz to dest_tz
*/
static inline date_t cm_adjust_date_between_two_tzs(date_t src_time, timezone_info_t src_tz,
timezone_info_t dest_tz)
{
return src_time + ((date_t)(dest_tz - src_tz)) * MICROSECS_PER_MIN;
}
static inline uint64 cm_day_usec(void)
{
#ifdef WIN32
uint64 usec;
SYSTEMTIME sys_time;
GetLocalTime(&sys_time);
usec = sys_time.wHour * SECONDS_PER_HOUR * MICROSECS_PER_SECOND;
usec += sys_time.wMinute * MICROSECS_PER_MIN;
usec += sys_time.wSecond * MICROSECS_PER_SECOND;
usec += sys_time.wMilliseconds * MICROSECS_PER_MILLISEC;
#else
uint64 usec;
struct timeval tv;
gettimeofday(&tv, NULL);
usec = (uint64)(tv.tv_sec * MICROSECS_PER_SECOND);
usec += (uint64)tv.tv_usec;
#endif
return usec;
}
static inline uint64 ogsql_timespec_func_diff_ns(const struct timespec *begin, const struct timespec *end)
{
if (end == NULL || begin == NULL) {
return 0;
}
if (end->tv_sec < begin->tv_sec ||
(end->tv_sec == begin->tv_sec && end->tv_nsec < begin->tv_nsec)) {
return 0;
}
uint64 sec_diff = (uint64)(end->tv_sec - begin->tv_sec) * NANOSECS_PER_SECOND_LL;
long nsec_diff = end->tv_nsec - begin->tv_nsec;
return sec_diff + (uint64)nsec_diff;
}
#ifndef WIN32
#define cm_gettimeofday(a) gettimeofday(a, NULL)
#else
#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)
#define OG_DELTA_EPOCH_IN_MICROSECS 11644473600000000Ui64
#else
#define OG_DELTA_EPOCH_IN_MICROSECS 11644473600000000ULL
#endif
int cm_gettimeofday(struct timeval *tv);
#endif
#define timeval_t struct timeval
#define TIMEVAL_DIFF_US(t_start, t_end) (((t_end)->tv_sec - (t_start)->tv_sec) * 1000000ULL + \
(t_end)->tv_usec - (t_start)->tv_usec)
#define TIMEVAL_DIFF_S(t_start, t_end) ((t_end)->tv_sec - (t_start)->tv_sec)
void cm_date2timeval(date_t date, struct timeval *val);
date_t cm_timeval2date(struct timeval tv);
date_t cm_timeval2realdate(struct timeval tv);
status_t cm_round_date(date_t date, text_t *fmt, date_t *result);
status_t cm_trunc_date(date_t date, text_t *fmt, date_t *result);
void cm_get_detail_ex(const date_detail_t *detail, date_detail_ex_t *detail_ex);
#ifdef __cplusplus
}
#endif
#endif