golang android time local 错误

1. 概述

在开发应用时,发现运行在android架构下go程序日志的打印时间错误。简单分析后,发现是时区错误。分析解决后,发现国内没有相关错误文章,所以写下文章帮助大家解决问题。

2. 需求

go程序运行在android系统下,日志打印时间与实际时间一致。

3. 条件

原本情况下,我们使用android架构编译的包是使用linux的os参数进行编译的,使用该参数的原因是直接android+arm会报编译失败(go17.5 丢失某些包)。使用linux的参数正常编译,使用也正常(日期还是异常)。

4. 现象

通过logcat观察输出的日志
08-05 17:26:10.266 I/xx( 4813): 2022-08-05T09:26:10.262Z [34mINFO[0m xxx.go:99 lxxx
17:26:10是实际时间,而go打印的是0时区的日志。

5. 验证

写了个简单的CLI程序,在android下跑。

log.Println(time.Now())

核心代码就使用标准log库打印时间。
发现log打印的时间也是+0的。

而使用adb命令可以观察android自己的时区是正确的。

6. 源码分析

go是由zoneinfo.go进行提供接口的,然后使用不同的os的实际使用。
例如,android使用的是link
简单分析后,android和unix(linux)都是通过读取特定文件来分析现在处在哪个时区。

// unix
var zoneSources = []string{
	"/usr/share/zoneinfo/",
	"/usr/share/lib/zoneinfo/",
	"/usr/lib/locale/TZ/",
	runtime.GOROOT() + "/lib/time/zoneinfo.zip",
}
// android
var zoneSources = []string{
	"/system/usr/share/zoneinfo/tzdata",
	"/data/misc/zoneinfo/current/tzdata",
	runtime.GOROOT() + "/lib/time/zoneinfo.zip",
}

但再去android系统(android11)中看,却都没有那些文件。因此会导致时区的识别失败。

7. 类似问题

识别到问题就到搜索引擎中查找类似问题,看看有没有讨论和解决方案。
终于,在bing中搜到bug
并且,该bug但还是go在github上的issue,且是open状态的。
文章中也描述的很清楚,并且还有源码中TODO字样。
因此,该问题确实是go的源码的bug,只是不知道什么时候才会修复。
修复的方法bug单也有讨论,才疏学浅我就不献丑了。

8. 解决方案

虽然go源码的修复不是你我讨论的,但实打实的问题还是要解决。
排除go源码的修复,还有可行的方案:

  • 不关注该时间,已知该问题,实际使用的问题也不大,自己眼睛换算下就行,等待go/android修复。这个方案实际在很多其他项目中都是这么使用的(github中该issue被其他项目提及可查)。
  • 统一使用utc时间戳,这个方案是讲的和云端的通信,使用utc时间戳,不要使用格式化的时间,本地日志打印的时间还是有问题。
  • 强制将时区进行调整。若程序不会运行在其他时区,可以强制改时区。扩展性差。
  • 曲线救国,生成源码指定路径的辅助时区文件。

强制改时区

虽然扩展性差,但还算能解决问题。由于我们的程序暂时不会在其他时区运行,所以就强制改时区了。
虽说是强制改时区,但go并没有给我们一次性改运行环境的时区的接口。
只能在每一次获取到时间,想要format时打印或上报时进行修正。

修正代码:

var location = time.FixedZone("CST", 8*60*60)

func GetLocation() *time.Location {
	return location
}

func ParseCSTTime(t time.Time) time.Time {
	return t.In(GetLocation())
}

这样等到go修复时也有退路,将输入值直接返回即可。
进阶:根据架构区分使用原生还是进行转换。
但还是不太优雅,暂时先这样吧。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值