前提:已安装好相应的扩展包
需求:
一般默认情况下,PHP写入到MongoDb中的日期,都是字段串或者时间戳;
现在需要保存为MongoDb中日期类型,可使用MongoDb中的日期函数进行计算
解决:
在扩展中类【MongoDB\BSON\Timestamp】,但在官方文档中提示不适合:
http://php.net/manual/zh/class.mongodb-bson-timestamp.php
Note: This is an internal MongoDB type used for replication and sharding. It is not intended for general date storage (MongoDB\BSON\UTCDateTime should be used instead).
在查看了其说明之后,不淡定了,没有时区设置,如果用它的话,都会转换为 零时区
MongoDB\BSON\UTCDateTime
测试代码如下,ThinkPHP 5.1 框架下写的,配置的时区为 东8区:
public function index() { $CNN = Db::connect('db_mongo')->table('kk'); $d = new UTCDateTime(); // 默认使用当前的 毫秒数 $d2 = new UTCDateTime(getMilliSecond()); // 写入指定日期,要转换为 毫秒;参数为毫秒数 $dateStr = '2019-03-01'; $d3 = new UTCDateTime(strtotime($dateStr) * 1000); // 入库,以上的时间入库,会比我们写入的 相关 8 个小时【时区差】 $id = $CNN->insertGetId(['now' => date('Y-m-d H:i:s'), 'd' => $d, 'd2' => $d2, 'd3' => $d3]); // 查询结果 $data = $CNN->where(['id' => $id])->find(); // 格式化回来,如果直接使用此 毫秒数格式化,则会 $dateTime = (new UTCDateTime($data['d']->milliseconds))->toDateTime(); return [ 'd' => $d, 'd2' => $d2, 'd3' => $d3, 'data' => $data, 'dateTime' => $dateTime, // 转换方法,根据配置的时区,把UTC时间 格式化为需要的时间 'localDate' => self::localDate($dateStr) ]; } private static function localDate(string $v, string $format = 'Y-m-d H:i:s') { $tz = new DateTimeZone(config('default_timezone')); // 修正时区 $date = (!empty($v)) ? $v : date("Y-m-d h:i:sa"); $a = new UTCDateTime(strtotime($date) * 1000); // 转为 UTC时间 $datetime = $a->toDateTime(); $datetime->setTimezone($tz); // 设置 时区 $time = $datetime->format($format); // 返回指定的格式 return $time; }
数据入库结果:
{ "_id": ObjectId("5c9484529dc6d605c3281df0"), "now": "2019-03-22 14:44:34", "d": ISODate("2019-03-22T06:44:34.362Z"), // 相差8小时 "d2": ISODate("2019-03-22T06:44:34.362Z"), "d3": ISODate("2019-02-28T16:00:00.000Z") }
解决:
1. 直接保存为字符串,然后用MongoDb的字符串处理函数
2. 使用【MongoDB\BSON\UTCDateTime】类,
2.1 转换,以【MongoDb的ISODate类型】保存,然后在程序取出数据,处理时区差
2.2 保存的时候,就根据做好时区差的计算
总结:
1. MongoDB\BSON\UTCDateTime 类,对应 MongoDb 的 ISODate
2. MongoDB\BSON\ObjectId 类,对应 MongoDb 的 ObjectId