理解时间戳和时区

作中经常有小伙伴分不清时间戳和时区,这里总结一下相关概念,并且不使用三方库函数,手动实现时间戳转日期功能。

概念

时区

世界时区的划分以本初子午线为标准,向东12个时区,向西12个时区,子午线所在区为0时区,东十二区和西十二区重合,所以一共是24个时区。

GMT和UTC

GMT: 即格林威治时间(Greenwich Mean Time),也是0时区的标准时间。指太阳横穿格林威治子午线(本初子午线)时的时间。但由于地球自转不均匀不规则,导致GMT不精确,现在已经不再作为世界标准时间使用。

UTC: 即协调世界时间(Coordinated Universal Time)。UTC是以原子时秒长为基础,在时刻上尽量接近于GMT的一种时间计量系统。UTC现在作为世界标准时间使用。

所以,UTC与GMT基本上等同,误差不超过0.9秒。

时间戳

UNIX时间戳:是从UTC时间1970年1月1日起到现在的秒数,不考虑闰秒,一天有86400秒,它是和时区无关的,无论在地球上的那个角落,同一时刻,UNIX时间戳都是一样的,计算机的本地时间就是根据 Unix时间戳 + 时区差 转换而来的。

本地时间

本地时间 = UTC + 时区差 时区差:东为正,西为负。在此,把东八区时区差记为 +0800, UTC 是标准时间参照,GMT(格林威治时间)、CST(北京时间)、PST(太平洋时间)等等是具体的时区,兑换如下:

GMT: UTC +0    =    GMT: GMT +0
CST: UTC +8    =    CST: GMT +8
PST: UTC -8    =    PST: GMT -8

手动实现时间戳转日期

思路:

  1. 获取时间戳
  2. 根据时间戳计算分钟,小时,天数,月份,年份。

Go实现

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
func main()  {

	var timestamp int64 = 1626751133 // 东八区 2021-07-20 11:18:53

	t := time.Unix(timestamp, 0)

	fmt.Println(t.Format("2006-01-02 15:04:05"))

	calcDate(timestamp)
}

// 计算日期
func calcDate(seconds int64)  {
var minutes, hours, days, year, month int64
var dayOfWeek int64
// 计算分钟
minutes  = seconds / 60
seconds -= minutes * 60
// 计算小时
hours    = minutes / 60
minutes -= hours   * 60
// 计算天数
days     = hours   / 24
hours   -= days    * 24

	year = 1970
	dayOfWeek = 4

	for {
		// 计算年份
		leapYear := false
		if year % 4 == 0 && (year % 100 != 0 || year % 400 == 0) {
			leapYear = true
		}
		var daysInYear int64 = 365
		if leapYear {
			daysInYear = 366
		}

		if days >= daysInYear {
			dayOfWeek += 1
			if leapYear {
				dayOfWeek += 2
			}
			days -= daysInYear
			if dayOfWeek >= 7 {
				dayOfWeek -= 7
			}
			year++
		} else {
			// 计算月份和天
			dayOfWeek  += days
			dayOfWeek  %= 7
			daysInMonth := [12]int64{31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31}
			for month = 0; month < 12; month++ {
				dim := daysInMonth[month]

				// 闰年并且是2月
				if month == 1 && leapYear {
					dim++
				}
				if days >= dim {
					days -= dim
				} else {
					break
				}
			}
			break
		}
	}

	fmt.Println("seconds:", seconds)
	fmt.Println("minutes:", minutes)
	fmt.Println("hours:", hours)
	fmt.Println("days:", days+1)
	fmt.Println("month:", month+1)
	fmt.Println("year:", year)
	fmt.Println("dayOfWeek:", dayOfWeek+1)
}

结果

2021-07-20 11:18:53
seconds: 53
minutes: 18
hours: 3
days: 20
month: 7
year: 2021
dayOfWeek: 2

因为计算的时间是UTC时间,所以将加8小时即是11点。

参考

updatedupdated2021-07-202021-07-20
Load Comments?