处理PHP和MySQL中的时区

时间:2016-06-16 05:22:23

标签: php mysql laravel timezone

我试图了解在应用程序堆栈中分别更改和转换时区和时间的确切原因是什么,以及在应用程序代码中将时间转换为所需时区的最佳方法。

我目前正在使用:

Javascript / HTML font end

Laravel PHP框架服务器端

MySQL存储(默认为时间戳的本地系统时间等)

我认为:

MySQL无法存储DateTime列的时区,只存储YYY:MM:DD hh:mm:ss,由开发人员将时区存储在单独的列等中,并将存储的时间转换为用户本地应用程序代码,如果用户时区不同。

PHP,Laravel应用程序应该工作并将任何DateTime实例转换为使用date_default_timezone_set()函数设置的时区。

我目前正在观察的行为:

我使用javascript日期时间格式设置对象属性回发json。这种格式对我来说是这样的:例如'2016年6月16日星期四18:00:00 GMT + 1000(AEST)'

当这个json数据到达我的服务器时,应用程序框架或PHP会自动将其转换为UTC,即使我将date_default_timezone_set('Australia / Sydney')放入控制器类或更改应用程序配置,替换了laravel UTC默认值。我怀疑有些东西没有注册?如果我能够节省来自客户端的时间(不会自动转换为UTC),如果用户位于澳大利亚/悉尼(其中大部分是用户),我将不必在以后将其转换为用户本地时区)。

我的应用程序将此UTC调整时间存储在数据库中,而实际上没有任何记录它是UTC。当然不是很重要因为我可以假定UTC的默认值。

当使用eloquent或DB:查询检索记录时,没有自动转换为用户时区,它只返回存储时间(转换为UTC),需要应用程序代码将其转换为正确的时区,否则用户(在我的情况下在澳大利亚)将查看UTC时间而不是当地的AEST等。

转换时间

如果从同一时区假定所有用户,是否有一种无忧无虑的方法可以自动将所有检索到的UTC时间从数据库转换为用户本地时区或某个指定的默认时区?

理想情况下,我想从数据库中提取记录,并将所有时间属性调整到指定的时区,同时考虑夏令时。我是否必须运行for循环并使用Carbon方法转换/设置每个属性等?

如果设置了date_default_timezone_set('Australia / Sydney')并且工作正常,那么PHP是否应该在从数据库中检索所有这些对象时自动转换time属性?以及在点击服务器时不将时间数据转换为UTC?

3 个答案:

答案 0 :(得分:1)

时区很烦人,毫无疑问。如果我正确理解你,你希望你的PHP将时间返回到用户正确区域的视图,对吗?

我所做的是在'主视图'或某种类型或blade.php文件中保证至少加载一次,我检查该用户的时区是否存储在会话变量中。如果不是,我向服务器发送一个AJAX请求来存储时区的名称。

RedirectMatch 301 /forum/news/(.*)-(.*) /news/$1

请注意,此方法使用jstz包,您可以download here将其包含在{{-- 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 部分中。

当然,您需要为此请求设置路由,对于我的情况,它看起来像这样:

<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')

解析日期

一般情况下,我建议您继续以UTC格式存储所有日期,因为这是标准,并且数据库保持时区不可知是不完美的。但是,如果您想更改默认设置,可以修改Carbon\Carbon::parse($date, $tz);中的行'timezone' => 'UTC'。这将覆盖Laravel默认其时间戳的区域,因此您的created_at,updated_at将被更改以反映新的时区。

答案 1 :(得分:0)

Agh - 好时光“如何处理时区”问题。就个人而言,我的一个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格式存储在数据库中。切勿将用户的时区格式化日期保存在数据库中。

答案 2 :(得分:0)

我不打算讨论时间戳的工作原理,但lemme告诉您如何有效地将日期时间存储在 MySQL 中以进一步使用它。以及为什么要在第一次存储时使用特定的模式来存储时区

date_default_timezone_set('Asia/Kolkata');
        $live_date = date('Y-m-d H:i:s');

使用此时间戳的优点是-

  1. 创建表时,可以在MySQL数据库中直接将数据类型指定为 DATETIME 。还将允许您使用此列对数据进行排序。

  2. 不仅在数据库中,而且如果您要在前端中使用jQuery Data表,您也会在这里获得好处,因为它还允许按时间排序。

  3. 在编写SQL查询以获取特定日期/时间范围的数据时,这种存储时间的方式效果很好,您只需编写即可

    BETWEEN date1 AND date2