问题
I am using MySQL json data type to store a JSON string.
In the JSON string are two fields: entry_time
, and entry_date
. The values for these fields are stored in ISO 8609 format as follows:
entry_date:2017-02-15T00:00:00.00Z
entry_time:0000-00-00T04:35:51.29Z
I am trying to create a virtual column from these two attributes. Since MySQL 5.7 has NO_ZERO_DATE
set I cannot see a way to extract these values out as date and time columns. Here is what I have tried:
alter table odh
add entry_time time GENERATED ALWAYS AS (REPLACE,(json_extract(jdoc,'$.entry_time')),'0000-00-00T','')
But I cannot get the sot work either Any help would be greatly appreciated!
回答1:
There's another problem past the NO_ZERO_DATE
problem: MySQL doesn't use ISO 8601 for dates, it uses ISO 9075 or SQL dates (really it uses all sorts of formats, MySQL date handling is pretty chaotic). There's some subtle differences, the biggest being that 9075 doesn't have the T in the middle. Most date APIs deal with this by making the T optional, but not MySQL.
mysql> select time('1234-01-01T04:35:51.29Z');
+---------------------------------+
| time('1234-01-01T04:35:51.29Z') |
+---------------------------------+
| 00:12:34 |
+---------------------------------+
1 row in set, 1 warning (0.00 sec)
Rather than giving an error, or ignoring the T, MySQL gave some desperately wrong answer.
mysql> select time('1234-01-01 04:35:51.29Z');
+---------------------------------+
| time('1234-01-01 04:35:51.29Z') |
+---------------------------------+
| 04:35:51.29 |
+---------------------------------+
1 row in set, 1 warning (0.00 sec)
Now it's fine.
Simplest thing to do is to replace the T with a space. Then TIME()
will work.
mysql> select time(replace('0000-00-00T04:35:51.29Z', 'T', ' '));
+------------------------------------------------+
| time(substring('0000-00-00T04:35:51.29Z', 12)) |
+------------------------------------------------+
| 04:35:51.29 |
+------------------------------------------------+
1 row in set, 1 warning (0.00 sec)
The date part will be handled by DATE()
, because MySQL will just ignore the rest.
mysql> select date('2017-02-15T00:00:00.00Z');
+---------------------------------+
| date('2017-02-15T00:00:00.00Z') |
+---------------------------------+
| 2017-02-15 |
+---------------------------------+
1 row in set, 1 warning (0.01 sec)
Rather than storing separate date and time columns, I'd strongly recommend you combine them into a single datetime
column. Especially if they're supposed to represent a single event (ie. 4:35:51.29 on 2017-20-15). This will make it much easier to do comparisons, and you can always extract the date and time parts with DATE()
and TIME()
.
回答2:
Not sure, but you might find some of this useful. Assuming you start with a json string brought over from the database:
$jsonstring = '{
"entries": [{
"entry_date": "2017-02-15T00:00:00.00Z",
"entry_time": "0000-00-00T04:35:51.29Z"
}, {
"entry_date": "2017-02-16T00:00:00.00Z",
"entry_time": "0000-00-00T05:21:08.12Z"
}, {
"entry_date": "2017-02-17T00:00:00.00Z",
"entry_time": "0000-00-00T07:14:55.04Z"
}]
}';
The following code will convert it to a single field:
$json = json_decode($jsonstring, true);
//display the json string before conversion
echo "<pre>";
print_r($json['entries']);
echo "</pre>";
$myArray = [];
for($i = 0; $i < count($json['entries']); $i++) {
$myArray[] = substr($json['entries'][$i]['entry_date'], 0, 10).
substr($json['entries'][$i]['entry_time'], 10);
}
//display the json string after conversion
echo "<pre>";
print_r($myArray);
echo "</pre>";
The result will look like this:
Array
(
[0] => 2017-02-15T04:35:51.29Z
[1] => 2017-02-16T05:21:08.12Z
[2] => 2017-02-17T07:14:55.04Z
)
来源:https://stackoverflow.com/questions/42305151/extracting-iso-dates-from-a-json-data-type