ThinkPHP Model 自动时间戳多时区处理

ThinkPHP Model 自动时间戳多时区处理

多语言侦测文章后,又遇到了时区的处理问题,每个人语言不同可能所在国家不同,时间也会不同,只显示一个固定时区的时间而不根据用户所在时区,可能会对用户体验造成一定影响。

当然,这里只是一个简单的示例,只是根据服务器的时区来做处理而不是用户真实的时区,如果需要根据用户则需要去获取用户 IP 所归属的国家(另外国外还有夏令时这些东东)。

修改下框架文件来支持:

vendor\topthink\think-orm\src\model\concern\TimeStamp.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
/**
* 时间日期字段格式化处理
* @access protected
* @param mixed $format 日期格式
* @param mixed $time 时间日期表达式
* @param bool $timestamp 时间表达式是否为时间戳
* @return mixed
*/
protected function formatDateTime($format, $time = 'now', bool $timestamp = false)
{
if (empty($time)) {
return;
}

if (false === $format) {
return $time;
} elseif (false !== strpos($format, '\\')) {
// return new $format($time);
$obj = new $format($time);
if (method_exists($obj, '__toString')) {
return $obj->__toString();
}
}

if ($time instanceof DateTime) {
$dateTime = $time;
} elseif ($timestamp) {
$dateTime = new DateTime();
$dateTime->setTimestamp((int) $time);
} else {
$dateTime = new DateTime($time);
}

return $dateTime->format($format);
}

app\util\AutoTimeZone.php

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
<?php
declare (strict_types = 1);

namespace app\util;

use DateTime;
use DateTimeZone;

class AutoTimeZone
{
protected $value;

public function __construct($value = null)
{
if(is_null($value)) {
// 为空需要返回一个 UTC 时间
$value = gmdate('Y-m-d H:i:s');
} else {
// 不为空则需要对 UTC 时间转换为本地时区
$date = new DateTime($value, new DateTimeZone('UTC'));
$date->setTimezone(new DateTimeZone(date_default_timezone_get()));
$value = $date->format('Y-m-d H:i:s');
}

$this->value = $value;
}

public function __toString()
{
return $this->value;
}
}

config\database.php

1
2
3
4
5
6
7
8
9
10
11
<?php

return [
// 自动写入时间戳字段
// true为自动识别类型 false关闭
// 字符串则明确指定时间字段类型 支持 int timestamp datetime date
'auto_timestamp' => true,

// 时间字段取出后的默认时间格式
'datetime_format' => '\\org\\util\\AutoTimeZone',
];
往上