!3586 to_date函数支持秒单位后使用小数点

Merge pull request !3586 from zhangzhixian/to_date_compat
This commit is contained in:
opengauss_bot
2023-06-27 03:15:31 +00:00
committed by Gitee
3 changed files with 90 additions and 14 deletions

View File

@ -5131,6 +5131,7 @@ struct pg_tm* GetDateDetail(const char* dateString)
strLength = strlen(dateString);
int decimalPointIndex = -1;
for (i = 0; i < strLength; i++) {
if (' ' == dateString[i]) {
if (spaceCount >= 5) {
@ -5139,12 +5140,24 @@ struct pg_tm* GetDateDetail(const char* dateString)
}
spacePosition[spaceCount] = i;
spaceCount++;
} else if ('.' == dateString[i]) {
if (decimalPointIndex != -1) {
pfree(tm);
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("the format is not correct")));
}
decimalPointIndex = i;
}
}
/* there is no space in the date-string*/
if (0 == spaceCount) {
/* assume that the string is this kind of fommat like "19900304123045"*/
if (DATE_WITHOUT_SPC_LEN == strLength) {
/*
* assume that the string is this kind of fommat like "19900304123045",
* or like "19900304123045.345" with decimal format of second
*/
#define DECIMAL_POINT_INDEX_IN_NO_SPACE_INPUT 14
if ((DATE_WITHOUT_SPC_LEN == strLength && decimalPointIndex == -1)
/* in condition like '19900304123045.345', make sure decimal point in position behind 'yyyymmddhhminss' */
|| (DATE_WITHOUT_SPC_LEN < strLength && decimalPointIndex == DECIMAL_POINT_INDEX_IN_NO_SPACE_INPUT)) {
SplitWholeStrWithoutSeparator(dateString, tm);
}
/* there is only specific date in the string but no time information in the string*/
@ -5161,7 +5174,8 @@ struct pg_tm* GetDateDetail(const char* dateString)
errno_t rc = strncpy_s(dateStr, DATESTR_LEN, dateString, spacePosition[0]);
securec_check(rc, "\0", "\0");
/* get the specific time*/
rc = strncpy_s(timeStr, TIMESTR_LEN, dateString + spacePosition[0] + 1, strLength - spacePosition[0]);
int count = strLength - spacePosition[0] <= TIMESTR_LEN ? strLength - spacePosition[0] : TIMESTR_LEN - 1;
rc = strncpy_s(timeStr, TIMESTR_LEN, dateString + spacePosition[0] + 1, count);
securec_check(rc, "\0", "\0");
AnalyseDate(dateStr, tm);
@ -5201,7 +5215,8 @@ void SplitWholeStrWithoutSeparator(const char* dateString, struct pg_tm* tm)
strLength = strlen(dateString);
for (i = 0; i < strLength; i++) {
if (dateString[i] < '0' || dateString[i] > '9') {
/* '.' will not count as nonDigit since we are now compatible with input format "19900304123045.345" */
if ((dateString[i] < '0' || dateString[i] > '9') && dateString[i] != '.') {
nonDigitCount++;
}
}
@ -5222,7 +5237,9 @@ void SplitWholeStrWithoutSeparator(const char* dateString, struct pg_tm* tm)
rc = strncpy_s(minute, UNIT_LEN, dateString + FOUR_DIGIT_LEN + TWO_DIGIT_LEN * 3, TWO_DIGIT_LEN);
securec_check(rc, "\0", "\0");
/* get second*/
rc = strncpy_s(second, UNIT_LEN, dateString + FOUR_DIGIT_LEN + TWO_DIGIT_LEN * 4, TWO_DIGIT_LEN);
int secondLength = (int)strlen(dateString + FOUR_DIGIT_LEN + TWO_DIGIT_LEN * 4);
int count = UNIT_LEN <= secondLength ? UNIT_LEN - 1 : secondLength;
rc = strncpy_s(second, UNIT_LEN, dateString + FOUR_DIGIT_LEN + TWO_DIGIT_LEN * 4, count);
securec_check(rc, "\0", "\0");
tm->tm_year = atoi(year);
@ -5230,7 +5247,7 @@ void SplitWholeStrWithoutSeparator(const char* dateString, struct pg_tm* tm)
tm->tm_mday = atoi(day);
tm->tm_hour = atoi(hour);
tm->tm_min = atoi(minute);
tm->tm_sec = atoi(second);
tm->tm_sec = (int)round(atof(second));
} else {
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("the format is not correct")));
}
@ -5356,6 +5373,7 @@ void AnalyseTime(const char* timeString, struct pg_tm* tm_time)
int i;
int timeSeparatorCount = 0;
int decimalPointCount = 0;
int timeSeparatorPosition[5] = {0};
if (NULL == timeString || NULL == tm_time) {
@ -5364,7 +5382,12 @@ void AnalyseTime(const char* timeString, struct pg_tm* tm_time)
}
strLength = strlen(timeString);
for (i = 0; i < strLength; i++) {
if (timeString[i] < '0' || timeString[i] > '9') {
if (timeString[i] == '.') {
decimalPointCount++;
if (decimalPointCount > 1) {
ereport(ERROR, (errcode(ERRCODE_INVALID_PARAMETER_VALUE), errmsg("the format is not correct")));
}
} else if (timeString[i] < '0' || timeString[i] > '9') {
timeSeparatorPosition[timeSeparatorCount] = i;
timeSeparatorCount++;
if (timeSeparatorCount > 5) {
@ -5428,13 +5451,9 @@ void SplitTimestrBySeparator(const char* timeString, int strLength, const int* s
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("the format is not correct")));
return;
}
if (MINLEN_TIME > strLength || MAXLEN_TIME < strLength) {
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("the time is not correct!")));
}
/* check the position of the oparator .1 and 2 are the posiible position of the first separator*/
else if (1 != separatorPosition[0] && 2 != separatorPosition[0]) {
if (1 != separatorPosition[0] && 2 != separatorPosition[0]) {
ereport(ERROR, (errcode(ERRCODE_FEATURE_NOT_SUPPORTED), errmsg("the hour is invalid!")));
}
/* 3 ,4 and 5 are the posiible position of the second separator*/
else if (3 != separatorPosition[1] && 4 != separatorPosition[1] && 5 != separatorPosition[1]) {
@ -5452,13 +5471,13 @@ void SplitTimestrBySeparator(const char* timeString, int strLength, const int* s
errorno = strncpy_s(second,
strLength - separatorPosition[1],
timeString + separatorPosition[1] + 1,
strLength - separatorPosition[1] - 1);
strLength - separatorPosition[1] - 1 < UNIT_LEN ? strLength - separatorPosition[1] - 1 : UNIT_LEN);
securec_check(errorno, "\0", "\0");
/* transfer char to int*/
tm_time->tm_hour = atoi(hour);
tm_time->tm_min = atoi(minute);
tm_time->tm_sec = atoi(second);
tm_time->tm_sec = (int)round(atof(second));
}
}

View File

@ -1038,3 +1038,51 @@ CONTEXT: referenced column: to_timestamp
SELECT to_timestamp(-999888762478);
ERROR: timestamp out of range: "-9.99889e+11"
CONTEXT: referenced column: to_timestamp
SELECT to_date('1992-01-01 12:34:56');
to_date
---------------------
1992-01-01 12:34:56
(1 row)
SELECT to_date('1992-01-01 12:34:56.545612164556');
to_date
---------------------
1992-01-01 12:34:57
(1 row)
SELECT to_date('1992-01-01 12:34:56.499999999999');
to_date
---------------------
1992-01-01 12:34:56
(1 row)
SELECT to_date('1992-01-01 12:34:56.500000000000');
to_date
---------------------
1992-01-01 12:34:57
(1 row)
SELECT to_date('19920101123456');
to_date
---------------------
1992-01-01 12:34:56
(1 row)
SELECT to_date('19920101123456.5848954380543');
to_date
---------------------
1992-01-01 12:34:57
(1 row)
SELECT to_date('19920101123456.5000000000000');
to_date
---------------------
1992-01-01 12:34:57
(1 row)
SELECT to_date('19920101123456.4999999999999');
to_date
---------------------
1992-01-01 12:34:56
(1 row)

View File

@ -270,3 +270,12 @@ SELECT to_timestamp(' Infinity'::float);
SELECT to_timestamp('-Infinity'::float);
SELECT to_timestamp('NaN'::float);
SELECT to_timestamp(-999888762478);
SELECT to_date('1992-01-01 12:34:56');
SELECT to_date('1992-01-01 12:34:56.545612164556');
SELECT to_date('1992-01-01 12:34:56.499999999999');
SELECT to_date('1992-01-01 12:34:56.500000000000');
SELECT to_date('19920101123456');
SELECT to_date('19920101123456.5848954380543');
SELECT to_date('19920101123456.5000000000000');
SELECT to_date('19920101123456.4999999999999');