处理PHP和MySQL中的时区
我想了解究竟是什么责任在我的应用程序堆栈中分别更改和转换时区和时间,以及在应用程序代码中将时间转换为所需时区的最佳方式是什么。
我目前正在使用:
Javascript / HTML字体结束
Laravel PHP框架服务器端
MySQL存储(默认为时间戳的本地系统时间等)
我认为:
MySQL不能为DateTime列存储时区,只能存储YYY:MM:DD hh:mm:ss,这取决于开发人员将时区存储在单独的列中,并将存储的时间转换为应用程序代码中的本地用户用户时区不同。
一个PHP,Laravel应用程序应该工作并将任何DateTime实例转换为使用date_default_timezone_set()函数设置的时区。
我目前观察到的行为:
我回发json与javascript日期时间格式设置的对象属性。 这种格式看起来是这样的:例如'Thu Jun 16 2016 18:00:00 GMT + 1000(AEST)'
当这个json数据碰到我的服务器时,即使我将date_default_timezone_set('Australia / Sydney')放入控制器类或更改应用程序配置,替换laravel UTC默认值,应用程序框架或PHP也会自动将其转换为UTC。 我怀疑有东西没有注册? 如果我能够节省时间,因为它来自客户端(不会自动转换为UTC),如果用户在澳大利亚/悉尼(这其中大部分是用户),我不必稍后将其转换为用户本地时区)。
我的应用程序将这个UTC调整时间存储在数据库中,而实际上没有任何记录它是UTC。 当然不是很重要,因为我可以推测UTC的默认值。
当使用雄辩或DB:查询检索记录时,不会自动转换为用户时区,它只是返回存储时间(转换为UTC),需要应用程序代码将其转换为正确的时区,否则用户(在澳大利亚我的情况)将看UTC时间,而不是当地的AEST等。
转换时间:
如果所有用户都是从同一个时区推定的,那么是否有一种方法可以自动将所有检索到的UTC时间从数据库转换为用户本地时区或某个指定的默认时区?
理想情况下,我想从数据库中提取记录并将所有时间属性调整为指定的时区,并考虑夏令时。 我将不得不运行一个for循环,并用Carbon方法等来转换/设置每个属性?
如果date_default_timezone_set('Australia / Sydney')被设置并且正常工作,PHP是否应该自动转换所有这些对象的时间属性,因为它们是从数据库中检索的? 当它打到服务器时不将时间数据转换为UTC?
时区很烦人,这是毫无疑问的。 如果我正确地理解了你,你希望你的PHP将时间返回给用户正确区域的视图,对吗?
我所做的是在“主视图”或某种或blade.php文件中保证至少加载一次,我检查此用户的时区是否存储在会话变量中。 如果不是,我发送一个AJAX请求到服务器来存储时区的名称。
{{-- store timezone in session variables --}}
@if (!Session::has('timezone'))
<script>
$(function () {
var tz = jstz.determine();
var data = {};
if (typeof (tz) !== 'undefined') {
data.timezone = tz.name();
}
if (!$.isEmptyObject(data)) {
$.ajax({
type: "POST",
url: "{{ url('/api/v1/settings') }}",
beforeSend: function (request) {
request.setRequestHeader("X-CSRF-TOKEN", "{{ csrf_token() }}");
},
data: $.param(data),
});
}
});
</script>
@endif
请注意,这种方法使用了jstz包,你可以在这里下载并包含在你的<head>
部分。
当然,你需要为这个请求设置路由,对于我的情况,它看起来像这样:
Route::post('api/v1/settings', function () {
// Save the user's timezone
if (Request::has('timezone')) {
Session::put('timezone', Request::get('timezone'));
}
});
现在,当您想要将给定的数据库日期时间字符串转换为正确的时区时,可以通过说$tz = $request->session()->get('timezone')
,然后用CarbonCarbon::parse($date, $tz);
解析出日期CarbonCarbon::parse($date, $tz);
一般来说,我会建议您保留所有日期的UTC格式,因为这是标准的,并且数据库保持时区不可知是不可知的。 但是如果你想改变默认值,你可以在config/app.php
编辑'timezone' => 'UTC'
这一行。 这将覆盖Laravel默认其时间戳的区域,因此您的created_at,updated_at将被更改以反映新的时区。
唉 - 好老的“如何处理时区”问题。 就我个人而言,在我的一个L5.2项目中,需要用户时区格式来显示数据。 我允许用户在帐户设置页面上选择/修改他们的时区。 然后我将它存储在数据库中,并建立关系进行检索。 例如,我有许多属于一家公司的用户。 所以在我的“公司”表中,我在这里有一个时区字段。 通过适当的关系,我可以像Auth::user()->company->timezone
那样访问它
然后我使用Carbon
解析与平台相关的所有日期。 例如, $current_date = Carbon:parse($date, Auth::user()->company->timezone);
。
事后看来,如果我不懒惰(有其他优先级)并且不需要更新一堆代码,我可能会为我的模型创建一个trait
来自动转换日期属性。
老实说,有很多方法 - 并且确定您的平台是否严重位于用户时区可能是一件棘手的事情。
例如,你可以在每个模型中做这样的事情(或者创建一个特征 - 最好的选择 - 存储这个)。 请注意,我以我的时区关系为例。 显然,将“some_date”等改为表名。 根据需要重复您需要转换的每个日期:
/**
* Convert date to user's timezone
*
* @return mixed
*/
public function setSomeDateAttribute($value)
{
$this->attributes['some_date'] = Carbon::parse($value, Auth::user()->company->timezone);
}
请注意,日期应始终作为UTC存储在数据库中。 切勿将用户的时区格式化日期保存在数据库中。
链接地址: http://www.djcxy.com/p/25053.html