我目前以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 Week
,Last 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进行比较,都会在用户时区显示星期一到星期日。
答案 0 :(得分:0)
您可以使用Laravel帮助程序功能配置来设置时区。但是,这只会影响您将收到的请求。
<强> config(['app.timezone' => $timezone]);
强>
如果您的目标是更改时区并在每个请求上运行,那么将更改的时区保存在数据库或文件中会怎么样。然后,编写DB查询或读取app / config.php中的文件,并在文件中更改索引时区的值。
答案 1 :(得分:0)
我最终为local
和utc
开始和结束日期创建了单独的返回属性。
下面是我的代码现在的样子:
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')),
];
}