MXS-2265: Fix formatting of the zero timestamp
The UNIX timestamp 0 should be treated as a special value and must be interpreted as 0-00-00 00:00:00 instead of 1970-01-01 00:00:00.
This commit is contained in:
@ -99,8 +99,6 @@ static const char* datetime_types[] =
|
|||||||
"DATETIME(4)",
|
"DATETIME(4)",
|
||||||
"DATETIME(5)",
|
"DATETIME(5)",
|
||||||
"DATETIME(6)",
|
"DATETIME(6)",
|
||||||
// TODO: Fix test setup to use same timezone
|
|
||||||
// "TIMESTAMP",
|
|
||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -112,6 +110,19 @@ static const char* datetime_values[] =
|
|||||||
NULL
|
NULL
|
||||||
};
|
};
|
||||||
|
|
||||||
|
static const char* timestamp_types[] =
|
||||||
|
{
|
||||||
|
"TIMESTAMP",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
|
static const char* timestamp_values[] =
|
||||||
|
{
|
||||||
|
"'2018-01-01 11:11:11'",
|
||||||
|
"'0-00-00 00:00:00'",
|
||||||
|
NULL
|
||||||
|
};
|
||||||
|
|
||||||
static const char* date_types[] =
|
static const char* date_types[] =
|
||||||
{
|
{
|
||||||
"DATE",
|
"DATE",
|
||||||
@ -156,6 +167,7 @@ struct
|
|||||||
{string_types, string_values},
|
{string_types, string_values},
|
||||||
{binary_types, binary_values},
|
{binary_types, binary_values},
|
||||||
{datetime_types, datetime_values},
|
{datetime_types, datetime_values},
|
||||||
|
{timestamp_types, timestamp_values},
|
||||||
{date_types, date_values},
|
{date_types, date_values},
|
||||||
{time_types, time_values},
|
{time_types, time_values},
|
||||||
{0, 0}
|
{0, 0}
|
||||||
|
@ -375,7 +375,16 @@ static void unpack_datetime2(uint8_t* ptr, uint8_t decimals, struct tm* dest)
|
|||||||
static void unpack_timestamp(uint8_t* ptr, uint8_t decimals, struct tm* dest)
|
static void unpack_timestamp(uint8_t* ptr, uint8_t decimals, struct tm* dest)
|
||||||
{
|
{
|
||||||
time_t t = unpack4(ptr);
|
time_t t = unpack4(ptr);
|
||||||
|
|
||||||
|
if (t == 0)
|
||||||
|
{
|
||||||
|
// Use GMT date to detect zero date timestamps
|
||||||
|
gmtime_r(&t, dest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
localtime_r(&t, dest);
|
localtime_r(&t, dest);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define unpack3(data) (data[2] + (data[1] << 8) + (data[0] << 16))
|
#define unpack3(data) (data[2] + (data[1] << 8) + (data[0] << 16))
|
||||||
@ -575,6 +584,13 @@ size_t unpack_temporal_value(uint8_t type, uint8_t* ptr, uint8_t* metadata, int
|
|||||||
return temporal_field_size(type, metadata, length);
|
return temporal_field_size(type, metadata, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool is_zero_date(struct tm* tm)
|
||||||
|
{
|
||||||
|
// Detects 1970-01-01 00:00:00
|
||||||
|
return tm->tm_sec == 0 && tm->tm_min == 0 && tm->tm_hour == 0
|
||||||
|
&& tm->tm_mday == 1 && tm->tm_mon == 0 && tm->tm_year == 70;
|
||||||
|
}
|
||||||
|
|
||||||
void format_temporal_value(char* str, size_t size, uint8_t type, struct tm* tm)
|
void format_temporal_value(char* str, size_t size, uint8_t type, struct tm* tm)
|
||||||
{
|
{
|
||||||
const char* format = "";
|
const char* format = "";
|
||||||
@ -606,7 +622,15 @@ void format_temporal_value(char* str, size_t size, uint8_t type, struct tm* tm)
|
|||||||
mxb_assert(false);
|
mxb_assert(false);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((type == TABLE_COL_TYPE_TIMESTAMP || type == TABLE_COL_TYPE_TIMESTAMP2) && is_zero_date(tm))
|
||||||
|
{
|
||||||
|
strcpy(str, "0-00-00 00:00:00");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
strftime(str, size, format, tm);
|
strftime(str, size, format, tm);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
Reference in New Issue
Block a user