如何使用Carbon将非本地时区日期字符串解析为当前默认时区?
我明白你的需求——已经通过date_default_timezone_set()设置好了全局时区,不想每次解析UTC格式的日期字符串时都手动指定时区,希望Carbon能自动帮你转换到默认时区对吧?
先解释下为什么直接解析不行:你拿到的2019-08-18T10:01:02Z里的Z是UTC时区的标识,Carbon解析这类带明确时区的字符串时,会把实例的时区设为UTC,所以直接format输出的就是UTC时间,不会自动切换到你设置的默认时区。
接下来给你几个不用到处写时区的解决方案:
方案1:利用时间戳转换(你已发现的思路,再细化下)
strtotime()会把UTC字符串转成UTC时间戳,而Carbon::createFromTimestamp()默认会使用PHP的默认时区来创建实例,一步就能得到转换后的时间:
$utcStr = '2019-08-18T10:01:02Z'; $carbon = Carbon::createFromTimestamp(strtotime($utcStr)); echo $carbon->format('Y-m-d H:i:s'); // 输出对应默认时区的时间,比如America/New_York下的2019-08-18 06:01:02
这个方法完全依赖你已经设置好的date_default_timezone_set(),不用额外指定任何时区,完美匹配你的需求。
方案2:设置Carbon全局默认时区,用内置方法转换
你可以在应用初始化的地方(比如Laravel的AppServiceProvider或者项目入口文件)设置一次Carbon的默认时区,和PHP的默认时区保持一致:
Carbon::setDefaultTimezone(date_default_timezone_get());
之后,每次解析UTC字符串后,只需调用toDefaultTimezone()方法,就能自动转换到全局设置的时区:
$carbon = Carbon::parse('2019-08-18T10:01:02Z')->toDefaultTimezone(); echo $carbon->format('Y-m-d H:i:s');
这个方案只需要一次全局配置,后续调用非常简洁,不用重复写时区相关代码。
方案3:封装全局辅助函数
如果你觉得每次调用toDefaultTimezone()还是有点麻烦,可以封装一个自己的辅助函数,放在项目的辅助文件里:
function carbon_utc_to_default($utcStr) { return Carbon::parse($utcStr)->setTimezone(date_default_timezone_get()); }
之后在任何地方直接调用这个函数就行:
$carbon = carbon_utc_to_default('2019-08-18T10:01:02Z'); echo $carbon->format('Y-m-d H:i:s');
总结一下,Carbon本身不会自动转换带明确时区的字符串到默认时区(因为要尊重原时间的时区信息),但通过上面的几种方法,你可以不用在每次解析时手动指定时区,只需要做一次全局配置或者用封装好的方法,就能达到你想要的效果。
内容的提问来源于stack exchange,提问作者Alex

