背景
在日志系统中调用localtime来转换为用户可见的时间(即距1970-01-01的秒数转换为年月日时分秒),会低概率的出现异常。原因是localtime()这个函数是线程不安全的,函数返回一个指向struct tm结构体的指针,这个指针指向一个静态变量。所以在多线程下,会概率性导致踩内存问题。
另外,虽然localtime_r()可以处理这个问题,但是localtime_r()的底层实现上,会对资源进行lock,在log系统里面使用该函数会造成一定程度上性能的损耗。
因此,需要一个可以快速将距1970-01-01的秒数转换为年月日时分秒的算法。
yyyy-mm-dd转换为距1970年的天数
1、将3月1号当做每年的第一天。如下表,mm是实际的月份,mp是转换之后的月份,doy是days-of-year,即距离每年的第一天的天数。
mm | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 1 | 2 |
---|---|---|---|---|---|---|---|---|---|---|---|---|
mp | 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 |
doy | 0 | 31 | 61 | 92 | 122 | 153 | 184 | 214 | 245 | 275 | 306 | 337 |
通过上表,可以推导出mp和doy的公式,如下:
doy = (153 * mp + 2) / 5 + dd - 1 // 这个式子是通过 (b1 * mp + b0) / a0这样一个公式假设出来的。
mp = (mm + 9) % 12 = mm + (mm > 2 ? -3 : 9)
2、由于每400年的总天数是相同的,因此以400年为单位进行计算。era指有多少个400年,yoe(years-of-era)是400年内的第几年,yp是转