Laravel中的用户时区问题

时间:2018-02-17 04:19:04

标签: php laravel timezone php-carbon

我目前以UTC格式存储所有日期。当用户登录时,它使用moment.js(moment.tz.guess()函数)来填充隐藏的时区输入及其时区名称,例如: America/Toronto,然后当他们登录时,用所述时区更新他们在数据库中的记录。

我创建了一个访问者特征,以显示用户时区中的所有日期。看到这段代码:

trait Timezone
{
    public function getCreatedAtAttribute($value)
    {
        return $this->timezone($value);
    }

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

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

    // convert date to user timezone
    public function timezone($value)
    {
        $carbon = Carbon::parse($value);

        if (auth()->check()) {
            $carbon->tz(auth()->user()->timezone);
        }

        return $carbon->toDateTimeString();
    }
}

现在我遇到了一个小问题。我在应用中有一个报告功能,它有一个下拉列表,用户可以在其中选择日期范围,例如This WeekLast Week等。

我将使用UTC来查询结果,然后将其转换为用户时区。问题是,对于一些用户来说,根据一天中的时间,本周显示为从星期二到星期一,或星期日到星期六,星期一到星期日,星期日。

这是我的代码:

public static function dateStartEnd($date_range)
{
    if ($date_range == 'Today') {
        $start_date = Carbon::now()->startOfDay();
        $end_date = Carbon::now()->endOfDay();
    }
    else if ($date_range == 'Yesterday') {
        $start_date = Carbon::now()->subDay()->startOfDay();
        $end_date = Carbon::now()->subDay()->endOfDay();
    }
    else if ($date_range == 'This Week') {
        $start_date = Carbon::now()->startOfWeek();
        $end_date = Carbon::now()->endOfWeek();
    }
    else if ($date_range == 'Last Week') {
        $start_date = Carbon::now()->subWeek()->startOfWeek();
        $end_date = Carbon::now()->subWeek()->endOfWeek();
    }
    else if ($date_range == 'This Month') {
        $start_date = Carbon::now()->startOfMonth();
        $end_date = Carbon::now()->endOfMonth();
    }
    else if ($date_range == 'Last Month') {
        $start_date = Carbon::now()->subMonth()->startOfMonth();
        $end_date = Carbon::now()->subMonth()->endOfMonth();
    }
    else {
        // All Time
        if ($lead = Lead::orderBy('created_at', 'asc')->first()) {
            $start_date = Carbon::parse($lead->created_at);
        }
        else {
            $start_date = Carbon::now()->startOfDay();
        }

        $end_date = Carbon::now()->endOfDay();
    }

    return [
        'start_date' => $start_date,
        'end_date' => $end_date,
    ];
}

我想知道如何正确地执行此操作,以便它可以使用UTC查询结果,但无论用户时区与UTC进行比较,都会在用户时区显示星期一到星期日。

2 个答案:

答案 0 :(得分:0)

您可以使用Laravel帮助程序功能配置来设置时区。但是,这只会影响您将收到的请求。

<强> config(['app.timezone' => $timezone]);

如果您的目标是更改时区并在每个请求上运行,那么将更改的时区保存在数据库或文件中会怎么样。然后,编写DB查询或读取app / config.php中的文件,并在文件中更改索引时区的值。

参考:: Change TimeZone dynamically in laravel

答案 1 :(得分:0)

我最终为localutc开始和结束日期创建了单独的返回属性。

下面是我的代码现在的样子:

public static function dateStartEnd($date_range, $date_from, $date_to)
{
    if ($date_range == 'Today') {
        $start_local = Carbon::now(auth()->user()->timezone)->startOfDay();
        $end_local = Carbon::now(auth()->user()->timezone)->endOfDay();
    }
    else if ($date_range == 'Yesterday') {
        $start_local = Carbon::now(auth()->user()->timezone)->subDay()->startOfDay();
        $end_local = Carbon::now(auth()->user()->timezone)->subDay()->endOfDay();
    }
    else if ($date_range == 'This Week') {
        $start_local = Carbon::now(auth()->user()->timezone)->startOfWeek();
        $end_local = Carbon::now(auth()->user()->timezone)->endOfWeek();
    }
    else if ($date_range == 'Last Week') {
        $start_local = Carbon::now(auth()->user()->timezone)->subWeek()->startOfWeek();
        $end_local = Carbon::now(auth()->user()->timezone)->subWeek()->endOfWeek();
    }
    else if ($date_range == 'This Month') {
        $start_local = Carbon::now(auth()->user()->timezone)->startOfMonth();
        $end_local = Carbon::now(auth()->user()->timezone)->endOfMonth();
    }
    else if ($date_range == 'Last Month') {
        $start_local = Carbon::now(auth()->user()->timezone)->subMonth()->startOfMonth();
        $end_local = Carbon::now(auth()->user()->timezone)->subMonth()->endOfMonth();
    }
    else if ($date_range == 'Custom') {
        $start_local = Carbon::parse($date_from, auth()->user()->timezone)->startOfDay();
        $end_local = Carbon::parse($date_to, auth()->user()->timezone)->endOfDay();
    }
    else {
        // All Time
        if ($lead = Lead::orderBy('created_at', 'asc')->first()) {
            $start_local = Carbon::parse($lead->created_at, auth()->user()->timezone);
        }
        else {
            $start_local = Carbon::now(auth()->user()->timezone)->startOfDay();
        }

        $end_local = Carbon::now(auth()->user()->timezone)->endOfDay();
    }

    return [
        'start_local' => $start_local,
        'start_utc' => $start_local->copy()->timezone(config('app.timezone')),
        'end_local' => $end_local,
        'end_utc' => $end_local->copy()->timezone(config('app.timezone')),
    ];
}