工作中遇到一个小需求,需要读取Linux环境下的一个文件中的日期,并将日期转换成秒数。
需求很简单很清晰,立马用go写了如下代码
func main() { fileName := "/xx/xx" b, err := ioutil.ReadFile(fileName) if err != nil { fmt.Println(err) } fmt.Println(string(b)) var LOC, _ = time.LoadLocation("Asia/Shanghai") t1, _ := time.ParseInLocation("2006-01-02 15:04:05",string(b) , LOC) fmt.Println(t1) fmt.Println(t1.Unix()) }
代码也很简单,第一步使用 ioutil.ReadFile方法读取文件,强转为string后,fmt打印文件中记录的日期;第二步使用time.ParseInLocation方法将日期相应格式转换为秒数,然后打印。完美。一个小需求花不到五分钟搞定。
但部署到环境上第二步打印结果为
0001-01-01 00:00:00 +0000 UTC
打印的秒数为
-62135596800
明显有坑啊。细致分析以后填了两个坑,但第二个坑让我耗了一天解决。。。
第一个坑:
第一步打印的日期格式为 “2022-5-30 7:49:24” 细看下来没问题,但再和规定日期格式对比一下,"2006-01-02 15:04:05",发现没,月和日格式,标准格式单数时十位会补0,但实际生产环境的日期却没有!
所以日期格式一定要跟需求人员对齐,不要想当然。将方法改为
time.ParseInLocation("2006-1-2 15:04:05",string(b) , LOC)
第一个坑,填好,搞定。
第二个坑:
第一个坑填好以后,我明显谨慎了一些,想着那就先在本地环境测一把再部。
第一把测试:
既然第一步日期已经打印出来了,我就定义一个string类型值为日期好了
abc :="2022-5-30 7:49:24" t1, _ := time.ParseInLocation("2006-1-2 15:04:05",abc , LOC)
本地测试,打印正确,够谨慎了吧,完美。
部署到环境,运行,报错。。。还是打印 0001-01-01 00:00:00 +0000 UTC
有意思。。。。。
开始排查问题,登陆到该Linux环境,使用cat xxx 命令查看该文件,没任何异样,孤零零的显示着日期 。
再vim xxx进去看一下,发现有些问题了,内容显示是这样的
后面有一些特殊符号,立马想到Linux环境下的文件可能会包含一些隐藏符号,这些符号可能代表空格,换行,空值等等。
那我手动把这些符号删掉呢?
vim进去把这些符号删掉,再把打印改一下:
fmt.Println(string(b)+"====") 想着加一下====,看打印是不是能把空格什么的打印出来
保存,运行,还是报错。。。。小样,还挺倔
而且发现第一把打印也不一样了,vim删掉符号之前打印是这样的
2022-5-30 7:49:24====
删掉符号后打印换行了
2022-5-30 7:49:24
====
问了一下小度小度,发现vim命令修改文件可能会自动换行(set nowrap set wrap 不过这一块也有点稀里糊涂的,感觉命令应该是超过一定长度后再自动换行,我这明显也没超过一定长度啊)
vim问题先搁置,文件还原到有特殊符号的原始状态,我开始钻牛角尖了,就算有特殊符号,但fmt.Println(string(b)+"====") 打印的时候,也没显示空格啊换行啊什么的啊,清清楚楚打印的
2022-5-30 7:49:24====
我把Linux环境的文件拷贝到本地window环境,用notepad++打开,发现文件是这样显示的
我再次把这些符号删掉,在本地运行了一把,打印正常。。。
这就尴尬了。。。
办法倒是有,使用正则只匹配日期格式的数字,冒号,横杠。
但需要这么复杂吗,我开始了怀疑人生,我只是单纯的读取了文件,而且文件内容也显示正常,怎么把string日期转换一下就不对了呢?
开始大量小度小度。。。发现文件读取命令,日期转换命令都没问题。
继续小度小度,发现了这篇文章:“ golang byte转string 字节数组转字符串的问题”
那看来就是在string(b)强行转换类型的时候出问题了,文章说的其实强转之后,fmt打印没问题,但如果对这个string再做其他处理就可能出问题了。
我们的代码正好是用这个强转后的string做日期格式转换处理,那就copy这个方法试一试吧。。。在Linux环境部署后,运行正常,搞定。。。
abc := byteString(b) t2, _ := time.ParseInLocation("2006-1-2 15:04:05",abc , LOC) fmt.Println(t2)
问题解决了,但其实还是遗留有疑问的
1、在window环境下,使用notepad++人为删除特殊符号,使用string(b)强转再转换日期格式,打印是正常的,但切换到Linux环境下,使用vim或者echo命令删除特殊符号,打印报错。------(个人认为还是因为使用vim等命令会默认换行,导致读取的string有换行符号,但实在懒得刨根问底了)
2、上面那个string转换函数其实没看懂,感觉好像也是为了处理结尾\0特殊符号的问题,实在懒得深挖了。。。