Khi nói đến việc phân tích chuỗi Ngày trong Go, chúng ta có thể sử dụng chức năng Phân tích cú pháp được cung cấp bởi gói thời gian. Trong Go, chúng tôi không sử dụng mã như hầu hết các ngôn ngữ khác để biểu thị các phần cấu thành của chuỗi ngày/giờ. Thay vào đó, Go sử dụng thiết bị ghi nhớ - thời gian tiêu chuẩn làm tài liệu tham khảo
Ví dụ: thời gian tham chiếu có thể trông như thế này -
Mon Jan 2 14:10:05 MST 2020 [MST is GMT-0700]
Hoặc, nó cũng có thể trông như thế này
01/02 03:04:10PM '20 -0700
cú pháp
Cú pháp của hàm Parse[] được hiển thị bên dưới
func Parse[layout, value string] [Time, error]
Hàm Parse lấy bố cục và giá trị làm đối số và trả về thời gian cũng như lỗi. Bố cục được sử dụng làm tham chiếu và giá trị là chuỗi ngày thực tế mà chúng tôi muốn phân tích cú pháp
ví dụ 1
Hãy xem xét mã được hiển thị bên dưới, trong đó chúng tôi sẽ sử dụng bố cục được xác định của riêng mình để phân tích ngày
package main import [ "fmt" "time" ] func main[] { v := "Thu, 05/19/11, 10:47PM" l := "Mon, 01/02/06, 03:04PM" tt, _ := time.Parse[l, v] fmt.Println[tt] }
đầu ra
Nếu chúng ta chạy đoạn mã trên bằng lệnh 2014-11-12 11. 45. 26. 371 +0000 UTC, sau đó chúng tôi sẽ nhận được đầu ra sau
2011-05-19 22:47:00 +0000 UTC
Thay vì chuyển một bố cục của riêng chúng tôi, chúng tôi cũng có thể chuyển một định dạng mà gói Go time cung cấp cho chúng tôi và nó cũng sẽ phân tích ngày tháng
Làm việc với các giá trị thời gian trong Go không đơn giản và việc sử dụng cơ sở dữ liệu để lưu trữ chúng bằng phân tích cú pháp tự động thậm chí còn thú vị hơn. Đây là những suy nghĩ của tôi về nó
Ngày 7 tháng 10 năm 2020 • 8 phút đọcGabor Javorszky
Trong quá trình thử nghiệm một tính năng, tôi phải tạo các đối tượng tạo ra thời gian hiện tại, lưu trữ nó trong cơ sở dữ liệu, đọc lại và đảm bảo rằng thời gian trên cả đối tượng mà tôi đã lưu trữ và đối tượng mà tôi lấy ra khỏi cơ sở dữ liệu
Trên đường đi tôi gặp rất nhiều điều kỳ lạ. Nguyên nhân đầu tiên là vì một lý do nào đó mà thời gian tôi nhập và thời gian tôi rút ra bị lệch đi một giờ, vì vậy tôi đã xem xét các phần khác nhau của nguyên nhân có thể gây ra tình trạng này.
Nói ngắn gọn về phần bên trong của time.Time
, cách xử lý múi giờ của nó, sau đó là cách xử lý múi giờ của kết nối cơ sở dữ liệu và máy chủ, điều đó có nghĩa là gì đối với việc lưu trữ dữ liệu và một loạt vấn đề ở cuối
Điều gì xảy ra trong time.Now[]
?
Cấu trúc của cấu trúc time.Time
là nó có ba bit khác nhau
- một cái gì đó gọi là "đồng hồ treo tường", đó là những gì chúng ta sử dụng khi nói thời gian. Đó là những gì bạn nhìn thấy khi nhìn vào đồng hồ trên tường, giả sử đồng hồ tuân theo DST tự động thay đổi. Thông thường, điều này sẽ không được sử dụng để nói khoảng thời gian giữa hai thời điểm khác nhau bởi vì nếu bạn xem thời gian ở 1. 58 giờ sáng ngày 25 tháng 10 tại Luân Đôn, và sau đó nhìn vào thời gian một giờ sau, nó sẽ hiện 1. 58 giờ sáng với sự khác biệt là 0 giữa các đồng hồ treo tường. Giờ mùa hè của Anh kết thúc lúc 2 giờ sáng ngày 25 tháng 10 năm 2020, vì vậy 2 giờ sáng -> 1 giờ sáng ngày hôm đó
- một cái gì đó gọi là đồng hồ đơn điệu. Điều này được khởi tạo vào thời điểm phiên bản thời gian mới được tạo và được sử dụng cho các chênh lệch thời gian. Một số phương pháp về thời gian sẽ loại bỏ đồng hồ đơn điệu khỏi ví dụ. Ví dụ:
.AddDate
,.Round
và.Truncate
- và một địa điểm. Vị trí chỉ được sử dụng cho mục đích hiển thị, nó không làm thay đổi giá trị thực của thời gian. Theo mặc định, vị trí sẽ dựa trên múi giờ địa phương của máy
"Múi giờ địa phương" là gì?
Tôi không biết điều này hoạt động như thế nào trên hệ thống Windows, nhưng trên hệ thống Unix [tôi đang dùng mac], trước tiên, nó xem xét biến môi trường
const dsn = "test:test@[localhost:3310]/test?parseTime=true&loc=Asia%2FTokyo"
0 là một chuỗi múi giờ, chẳng hạn như const dsn = "test:test@[localhost:3310]/test?parseTime=true&loc=Asia%2FTokyo"
1 hoặc const dsn = "test:test@[localhost:3310]/test?parseTime=true&loc=Asia%2FTokyo"
2 hoặc const dsn = "test:test@[localhost:3310]/test?parseTime=true&loc=Asia%2FTokyo"
3Nếu
const dsn = "test:test@[localhost:3310]/test?parseTime=true&loc=Asia%2FTokyo"
0 không được đặt, thì nó sẽ lấy vị trí có tên là const dsn = "test:test@[localhost:3310]/test?parseTime=true&loc=Asia%2FTokyo"
5 từ thư mục const dsn = "test:test@[localhost:3310]/test?parseTime=true&loc=Asia%2FTokyo"
6 trên hệ thốngconst dsn = "test:test@[localhost:3310]/test?parseTime=true&loc=Asia%2FTokyo"
7 là một liên kết tượng trưng đến nhị phân vị trí thực tế. Trên máy mac, bạn sẽ đặt nó trong tùy chọn hệ thốngCài đặt ở trên dẫn đến kết quả này
$ ls -la /etc/localtime
lrwxr-xr-x 1 root wheel 36 8 Oct 00:21 /etc/localtime -> /var/db/timezone/zoneinfo/Asia/Tokyo
Giờ địa phương trong vùng chứa docker
Cách đặt múi giờ của bộ chứa docker là đặt biến môi trường
const dsn = "test:test@[localhost:3310]/test?parseTime=true&loc=Asia%2FTokyo"
0 của nóĐiều gì xảy ra trong một kết nối SQL?
Có hai múi giờ mà chúng ta cần xử lý trong cơ sở dữ liệu MySQL
- múi giờ của hệ thống, đó là những gì máy chủ mysql sẽ sử dụng
- và múi giờ của chính kết nối
kết nối SQL
Đặt múi giờ của kết nối là cách dễ dàng hơn. dsn [tên nguồn dữ liệu] có thể chứa một loạt các tham số. Một dsn đầy đủ tôi sẽ sử dụng trong mã của mình trông như thế này
const dsn = "test:test@[localhost:3310]/test?parseTime=true&loc=Asia%2FTokyo"
Ở đây tôi đang đặt kết nối thành
const dsn = "test:test@[localhost:3310]/test?parseTime=true&loc=Asia%2FTokyo"
3máy chủ SQL
Nếu máy chủ mysql đang chạy cục bộ, rất có thể nó sử dụng cùng múi giờ với hệ thống của bạn. Nếu không, bạn có thể định cấu hình nó bằng cờ dòng lệnh
// connection is America/Phoenix
db, _ := sql.Open["mysql", mysqlDSN]
// table has an auto-increment id and a timestamp colum ts
insert, _ := db.Prepare["INSERT INTO table [ts] VALUES [?]"]
// ts is now 2020-10-07 12:00:00+01:00 for BST
ts := time.Now[]
results, _ := insert.Exec[ts]
id, _ := results.LastInsertId[]
// then we open another connection, this time the tz is Europe/London
db2, _ := sql.Open["mysql", mysqlDSN2]
select, _ := db.Prepare["SELECT * FROM table WHERE id = ?"]
// we get the same row out that we inserted previously
rows, _ := select.Exec[id]
var id int64
var gotTime time.Time
for rows.Next[] {
_ = rows.Scan[&id, &gotTime]
}
// compare the times
fmt.Printf["in: %s\nout: %s",
ts.In[time.UTC].Format[time.RFC3339Nano],
gotTime.In[time.UTC].Format[time.RFC3339Nano]]
// this will print:
in: 2020-10-07 11:00:00.703337Z
out: 2020-10-07 11:00:00Z
0 hoặc đưa ra lệnh // connection is America/Phoenix
db, _ := sql.Open["mysql", mysqlDSN]
// table has an auto-increment id and a timestamp colum ts
insert, _ := db.Prepare["INSERT INTO table [ts] VALUES [?]"]
// ts is now 2020-10-07 12:00:00+01:00 for BST
ts := time.Now[]
results, _ := insert.Exec[ts]
id, _ := results.LastInsertId[]
// then we open another connection, this time the tz is Europe/London
db2, _ := sql.Open["mysql", mysqlDSN2]
select, _ := db.Prepare["SELECT * FROM table WHERE id = ?"]
// we get the same row out that we inserted previously
rows, _ := select.Exec[id]
var id int64
var gotTime time.Time
for rows.Next[] {
_ = rows.Scan[&id, &gotTime]
}
// compare the times
fmt.Printf["in: %s\nout: %s",
ts.In[time.UTC].Format[time.RFC3339Nano],
gotTime.In[time.UTC].Format[time.RFC3339Nano]]
// this will print:
in: 2020-10-07 11:00:00.703337Z
out: 2020-10-07 11:00:00Z
1. Xem tài liệu MySQL về hỗ trợ múi giờ để biết thêm thông tin đầy đủĐiều này rất quan trọng vì cột
// connection is America/Phoenix
db, _ := sql.Open["mysql", mysqlDSN]
// table has an auto-increment id and a timestamp colum ts
insert, _ := db.Prepare["INSERT INTO table [ts] VALUES [?]"]
// ts is now 2020-10-07 12:00:00+01:00 for BST
ts := time.Now[]
results, _ := insert.Exec[ts]
id, _ := results.LastInsertId[]
// then we open another connection, this time the tz is Europe/London
db2, _ := sql.Open["mysql", mysqlDSN2]
select, _ := db.Prepare["SELECT * FROM table WHERE id = ?"]
// we get the same row out that we inserted previously
rows, _ := select.Exec[id]
var id int64
var gotTime time.Time
for rows.Next[] {
_ = rows.Scan[&id, &gotTime]
}
// compare the times
fmt.Printf["in: %s\nout: %s",
ts.In[time.UTC].Format[time.RFC3339Nano],
gotTime.In[time.UTC].Format[time.RFC3339Nano]]
// this will print:
in: 2020-10-07 11:00:00.703337Z
out: 2020-10-07 11:00:00Z
2 mà chúng tôi đang sử dụngTLDR của
// connection is America/Phoenix
db, _ := sql.Open["mysql", mysqlDSN]
// table has an auto-increment id and a timestamp colum ts
insert, _ := db.Prepare["INSERT INTO table [ts] VALUES [?]"]
// ts is now 2020-10-07 12:00:00+01:00 for BST
ts := time.Now[]
results, _ := insert.Exec[ts]
id, _ := results.LastInsertId[]
// then we open another connection, this time the tz is Europe/London
db2, _ := sql.Open["mysql", mysqlDSN2]
select, _ := db.Prepare["SELECT * FROM table WHERE id = ?"]
// we get the same row out that we inserted previously
rows, _ := select.Exec[id]
var id int64
var gotTime time.Time
for rows.Next[] {
_ = rows.Scan[&id, &gotTime]
}
// compare the times
fmt.Printf["in: %s\nout: %s",
ts.In[time.UTC].Format[time.RFC3339Nano],
gotTime.In[time.UTC].Format[time.RFC3339Nano]]
// this will print:
in: 2020-10-07 11:00:00.703337Z
out: 2020-10-07 11:00:00Z
2 là nó lưu trữ thời gian dưới dạng UTC và hiển thị cho bạn giá trị dựa trên kết nối của bạn với cơ sở dữ liệu. Điều đó cũng có nghĩa là khi lưu trữ giá trị, bất kỳ chuỗi nào đến, MySQL sẽ cho rằng nó nằm trong múi giờ của kết nối. Xem bài viết trước của tôi về các sắc thái của // connection is America/Phoenix
db, _ := sql.Open["mysql", mysqlDSN]
// table has an auto-increment id and a timestamp colum ts
insert, _ := db.Prepare["INSERT INTO table [ts] VALUES [?]"]
// ts is now 2020-10-07 12:00:00+01:00 for BST
ts := time.Now[]
results, _ := insert.Exec[ts]
id, _ := results.LastInsertId[]
// then we open another connection, this time the tz is Europe/London
db2, _ := sql.Open["mysql", mysqlDSN2]
select, _ := db.Prepare["SELECT * FROM table WHERE id = ?"]
// we get the same row out that we inserted previously
rows, _ := select.Exec[id]
var id int64
var gotTime time.Time
for rows.Next[] {
_ = rows.Scan[&id, &gotTime]
}
// compare the times
fmt.Printf["in: %s\nout: %s",
ts.In[time.UTC].Format[time.RFC3339Nano],
gotTime.In[time.UTC].Format[time.RFC3339Nano]]
// this will print:
in: 2020-10-07 11:00:00.703337Z
out: 2020-10-07 11:00:00Z
2 và // connection is America/Phoenix
db, _ := sql.Open["mysql", mysqlDSN]
// table has an auto-increment id and a timestamp colum ts
insert, _ := db.Prepare["INSERT INTO table [ts] VALUES [?]"]
// ts is now 2020-10-07 12:00:00+01:00 for BST
ts := time.Now[]
results, _ := insert.Exec[ts]
id, _ := results.LastInsertId[]
// then we open another connection, this time the tz is Europe/London
db2, _ := sql.Open["mysql", mysqlDSN2]
select, _ := db.Prepare["SELECT * FROM table WHERE id = ?"]
// we get the same row out that we inserted previously
rows, _ := select.Exec[id]
var id int64
var gotTime time.Time
for rows.Next[] {
_ = rows.Scan[&id, &gotTime]
}
// compare the times
fmt.Printf["in: %s\nout: %s",
ts.In[time.UTC].Format[time.RFC3339Nano],
gotTime.In[time.UTC].Format[time.RFC3339Nano]]
// this will print:
in: 2020-10-07 11:00:00.703337Z
out: 2020-10-07 11:00:00Z
5 trong MySQL nơi tôi đã tìm hiểu về múi giờ và MySQLnhư một ví dụ.
// connection is America/Phoenix
db, _ := sql.Open["mysql", mysqlDSN]
// table has an auto-increment id and a timestamp colum ts
insert, _ := db.Prepare["INSERT INTO table [ts] VALUES [?]"]
// ts is now 2020-10-07 12:00:00+01:00 for BST
ts := time.Now[]
results, _ := insert.Exec[ts]
id, _ := results.LastInsertId[]
// then we open another connection, this time the tz is Europe/London
db2, _ := sql.Open["mysql", mysqlDSN2]
select, _ := db.Prepare["SELECT * FROM table WHERE id = ?"]
// we get the same row out that we inserted previously
rows, _ := select.Exec[id]
var id int64
var gotTime time.Time
for rows.Next[] {
_ = rows.Scan[&id, &gotTime]
}
// compare the times
fmt.Printf["in: %s\nout: %s",
ts.In[time.UTC].Format[time.RFC3339Nano],
gotTime.In[time.UTC].Format[time.RFC3339Nano]]
// this will print:
in: 2020-10-07 11:00:00.703337Z
out: 2020-10-07 11:00:00Z
6 với múi giờ kết nối là // connection is America/Phoenix
db, _ := sql.Open["mysql", mysqlDSN]
// table has an auto-increment id and a timestamp colum ts
insert, _ := db.Prepare["INSERT INTO table [ts] VALUES [?]"]
// ts is now 2020-10-07 12:00:00+01:00 for BST
ts := time.Now[]
results, _ := insert.Exec[ts]
id, _ := results.LastInsertId[]
// then we open another connection, this time the tz is Europe/London
db2, _ := sql.Open["mysql", mysqlDSN2]
select, _ := db.Prepare["SELECT * FROM table WHERE id = ?"]
// we get the same row out that we inserted previously
rows, _ := select.Exec[id]
var id int64
var gotTime time.Time
for rows.Next[] {
_ = rows.Scan[&id, &gotTime]
}
// compare the times
fmt.Printf["in: %s\nout: %s",
ts.In[time.UTC].Format[time.RFC3339Nano],
gotTime.In[time.UTC].Format[time.RFC3339Nano]]
// this will print:
in: 2020-10-07 11:00:00.703337Z
out: 2020-10-07 11:00:00Z
7 giá trị UTC cơ bản là // connection is America/Phoenix
db, _ := sql.Open["mysql", mysqlDSN]
// table has an auto-increment id and a timestamp colum ts
insert, _ := db.Prepare["INSERT INTO table [ts] VALUES [?]"]
// ts is now 2020-10-07 12:00:00+01:00 for BST
ts := time.Now[]
results, _ := insert.Exec[ts]
id, _ := results.LastInsertId[]
// then we open another connection, this time the tz is Europe/London
db2, _ := sql.Open["mysql", mysqlDSN2]
select, _ := db.Prepare["SELECT * FROM table WHERE id = ?"]
// we get the same row out that we inserted previously
rows, _ := select.Exec[id]
var id int64
var gotTime time.Time
for rows.Next[] {
_ = rows.Scan[&id, &gotTime]
}
// compare the times
fmt.Printf["in: %s\nout: %s",
ts.In[time.UTC].Format[time.RFC3339Nano],
gotTime.In[time.UTC].Format[time.RFC3339Nano]]
// this will print:
in: 2020-10-07 11:00:00.703337Z
out: 2020-10-07 11:00:00Z
8Cùng một giá trị
// connection is America/Phoenix
db, _ := sql.Open["mysql", mysqlDSN]
// table has an auto-increment id and a timestamp colum ts
insert, _ := db.Prepare["INSERT INTO table [ts] VALUES [?]"]
// ts is now 2020-10-07 12:00:00+01:00 for BST
ts := time.Now[]
results, _ := insert.Exec[ts]
id, _ := results.LastInsertId[]
// then we open another connection, this time the tz is Europe/London
db2, _ := sql.Open["mysql", mysqlDSN2]
select, _ := db.Prepare["SELECT * FROM table WHERE id = ?"]
// we get the same row out that we inserted previously
rows, _ := select.Exec[id]
var id int64
var gotTime time.Time
for rows.Next[] {
_ = rows.Scan[&id, &gotTime]
}
// compare the times
fmt.Printf["in: %s\nout: %s",
ts.In[time.UTC].Format[time.RFC3339Nano],
gotTime.In[time.UTC].Format[time.RFC3339Nano]]
// this will print:
in: 2020-10-07 11:00:00.703337Z
out: 2020-10-07 11:00:00Z
6 với múi giờ kết nối là const dsn = "test:test@[localhost:3310]/test?parseTime=true&loc=Asia%2FTokyo"
3 sẽ có giá trị UTC cơ bản là ts.In[connection.Timezone].Format[mysqlDateTimeFormat]
1Múi giờ của máy chủ MySQL sẽ rất quan trọng đối với dấu thời gian hiện tại
Giờ địa phương hiện tại ở London là
ts.In[connection.Timezone].Format[mysqlDateTimeFormat]
2, kết nối SQL cũng là // connection is America/Phoenix
db, _ := sql.Open["mysql", mysqlDSN]
// table has an auto-increment id and a timestamp colum ts
insert, _ := db.Prepare["INSERT INTO table [ts] VALUES [?]"]
// ts is now 2020-10-07 12:00:00+01:00 for BST
ts := time.Now[]
results, _ := insert.Exec[ts]
id, _ := results.LastInsertId[]
// then we open another connection, this time the tz is Europe/London
db2, _ := sql.Open["mysql", mysqlDSN2]
select, _ := db.Prepare["SELECT * FROM table WHERE id = ?"]
// we get the same row out that we inserted previously
rows, _ := select.Exec[id]
var id int64
var gotTime time.Time
for rows.Next[] {
_ = rows.Scan[&id, &gotTime]
}
// compare the times
fmt.Printf["in: %s\nout: %s",
ts.In[time.UTC].Format[time.RFC3339Nano],
gotTime.In[time.UTC].Format[time.RFC3339Nano]]
// this will print:
in: 2020-10-07 11:00:00.703337Z
out: 2020-10-07 11:00:00Z
7, máy chủ SQL là const dsn = "test:test@[localhost:3310]/test?parseTime=true&loc=Asia%2FTokyo"
3. Khi tôi thực hiện một ts.In[connection.Timezone].Format[mysqlDateTimeFormat]
5 và ngay lập tức truy vấn lại nó, tôi sẽ nhận được ts.In[connection.Timezone].Format[mysqlDateTimeFormat]
6Hãy nói về các câu lệnh parseTime và SQL
Tầm quan trọng của
ts.In[connection.Timezone].Format[mysqlDateTimeFormat]
7 trong dsn là đưa ra một tuyên bố đã chuẩn bị sẵn và một đối số time.Time
, người lái xe sẽ đảm bảo rằng thời gian. Thời gian sẽ được chuyển thành định dạng và múi giờ cần thiết trước khi lưu trữĐiều đó cũng có nghĩa là khi quét các giá trị ra khỏi bảng có dấu thời gian [hoặc cột ngày giờ, ngày tháng, thời gian] sẽ được mở ra thành một thể hiện time.Time
thay vì một time.Time
0
Xem xét đoạn mã này [xử lý lỗi và nhập bị bỏ qua]
// connection is America/Phoenix
db, _ := sql.Open["mysql", mysqlDSN]
// table has an auto-increment id and a timestamp colum ts
insert, _ := db.Prepare["INSERT INTO table [ts] VALUES [?]"]
// ts is now 2020-10-07 12:00:00+01:00 for BST
ts := time.Now[]
results, _ := insert.Exec[ts]
id, _ := results.LastInsertId[]
// then we open another connection, this time the tz is Europe/London
db2, _ := sql.Open["mysql", mysqlDSN2]
select, _ := db.Prepare["SELECT * FROM table WHERE id = ?"]
// we get the same row out that we inserted previously
rows, _ := select.Exec[id]
var id int64
var gotTime time.Time
for rows.Next[] {
_ = rows.Scan[&id, &gotTime]
}
// compare the times
fmt.Printf["in: %s\nout: %s",
ts.In[time.UTC].Format[time.RFC3339Nano],
gotTime.In[time.UTC].Format[time.RFC3339Nano]]
// this will print:
in: 2020-10-07 11:00:00.703337Z
out: 2020-10-07 11:00:00Z
Lưu ý rằng nano giây [phần time.Time
1] bị thiếu trong thời gian "hết". Đó là bởi vì khi chúng tôi tạo thời gian với time.Now[]
, Go đã quản lý để đo nano giây tại thời điểm nó được tạo
Tuy nhiên, việc đưa dữ liệu đó vào cơ sở dữ liệu với định dạng ngày của MySQL [time.Time
3] không có độ phân giải để lưu trữ nano giây, do đó, khi đọc dấu thời gian, không thể tạo lại nano giây¹
tuyên bố. Exec nội bộ cho thời gian. phân tích thời gian
Nó sẽ lặp qua tất cả các đối số, kiểm tra loại của chúng và nếu đó là một time.Time
, trước tiên, nó sẽ thay đổi vị trí múi giờ của nó thành bất kỳ múi giờ nào của kết nối, sau đó định dạng nó thành định dạng dấu thời gian của MySQL và chuyển nó tới
Về bản chất, nó đang làm điều này
ts.In[connection.Timezone].Format[mysqlDateTimeFormat]
Nếu bạn muốn xem mã thực tế trong phiên bản 1. 5. 0 của trình điều khiển mysql.
hàng. Quét nội bộ cho thời gian. phân tích thời gian
Bên trong trình điều khiển [time.Time
5] sẽ trả về một tập kết quả time.Time
6 cốt lõi
Phương thức time.Time
7 trên cấu trúc đó sẽ gọi một hàm có tên là time.Time
8 cho mỗi cột, nơi nó sẽ lấy time.Time
9, con trỏ tới loại bạn đang quét và nguồn, kết quả trả về từ cơ sở dữ liệu cho
Trên thực tế, điều này có nghĩa là nếu kết nối có time.Now[]
0 trên dsn, bất kỳ giá trị nào có
// connection is America/Phoenix
db, _ := sql.Open["mysql", mysqlDSN]
// table has an auto-increment id and a timestamp colum ts
insert, _ := db.Prepare["INSERT INTO table [ts] VALUES [?]"]
// ts is now 2020-10-07 12:00:00+01:00 for BST
ts := time.Now[]
results, _ := insert.Exec[ts]
id, _ := results.LastInsertId[]
// then we open another connection, this time the tz is Europe/London
db2, _ := sql.Open["mysql", mysqlDSN2]
select, _ := db.Prepare["SELECT * FROM table WHERE id = ?"]
// we get the same row out that we inserted previously
rows, _ := select.Exec[id]
var id int64
var gotTime time.Time
for rows.Next[] {
_ = rows.Scan[&id, &gotTime]
}
// compare the times
fmt.Printf["in: %s\nout: %s",
ts.In[time.UTC].Format[time.RFC3339Nano],
gotTime.In[time.UTC].Format[time.RFC3339Nano]]
// this will print:
in: 2020-10-07 11:00:00.703337Z
out: 2020-10-07 11:00:00Z
2, // connection is America/Phoenix
db, _ := sql.Open["mysql", mysqlDSN]
// table has an auto-increment id and a timestamp colum ts
insert, _ := db.Prepare["INSERT INTO table [ts] VALUES [?]"]
// ts is now 2020-10-07 12:00:00+01:00 for BST
ts := time.Now[]
results, _ := insert.Exec[ts]
id, _ := results.LastInsertId[]
// then we open another connection, this time the tz is Europe/London
db2, _ := sql.Open["mysql", mysqlDSN2]
select, _ := db.Prepare["SELECT * FROM table WHERE id = ?"]
// we get the same row out that we inserted previously
rows, _ := select.Exec[id]
var id int64
var gotTime time.Time
for rows.Next[] {
_ = rows.Scan[&id, &gotTime]
}
// compare the times
fmt.Printf["in: %s\nout: %s",
ts.In[time.UTC].Format[time.RFC3339Nano],
gotTime.In[time.UTC].Format[time.RFC3339Nano]]
// this will print:
in: 2020-10-07 11:00:00.703337Z
out: 2020-10-07 11:00:00Z
5, time.Now[]
3, time.Now[]
4 sẽ kết thúc dưới dạng giá trị time.Time
với vị trí được đặt làm múi giờ của kết nối, giống như trênNếu sau đó biến bạn đang quét cũng là một time.Time
, thì bạn chỉ cần lấy lại giá trị đó ngay lập tức. Nếu bạn đang quét một time.Time
thành một chuỗi, thì bạn sẽ lấy lại biểu diễn time.Now[]
8 của giá trị được lưu trữ
Đây là
Điều quan trọng cần lưu ý là nếu time.Now[]
0 không có trên dsn, thì giá trị của cột
// connection is America/Phoenix
db, _ := sql.Open["mysql", mysqlDSN]
// table has an auto-increment id and a timestamp colum ts
insert, _ := db.Prepare["INSERT INTO table [ts] VALUES [?]"]
// ts is now 2020-10-07 12:00:00+01:00 for BST
ts := time.Now[]
results, _ := insert.Exec[ts]
id, _ := results.LastInsertId[]
// then we open another connection, this time the tz is Europe/London
db2, _ := sql.Open["mysql", mysqlDSN2]
select, _ := db.Prepare["SELECT * FROM table WHERE id = ?"]
// we get the same row out that we inserted previously
rows, _ := select.Exec[id]
var id int64
var gotTime time.Time
for rows.Next[] {
_ = rows.Scan[&id, &gotTime]
}
// compare the times
fmt.Printf["in: %s\nout: %s",
ts.In[time.UTC].Format[time.RFC3339Nano],
gotTime.In[time.UTC].Format[time.RFC3339Nano]]
// this will print:
in: 2020-10-07 11:00:00.703337Z
out: 2020-10-07 11:00:00Z
2 sẽ trả về dưới dạng time.Time
0, tại thời điểm đó bạn không thể quét nó thành biến time.Time
Điều này có ý nghĩa gì đối với thử nghiệm?
Tất cả những điều trên có nghĩa là như sau
time.Now[]
sẽ Just Work™ với mọi thứ. Những gì bạn đưa vào là những gì bạn sẽ nhận ra vì cả ba múi giờ đều được tính đến [hệ thống cục bộ của bạn, kết nối SQL và máy chủ SQL]- khi bạn đang tạo thời gian mới dựa trên một chuỗi có
time.Time
4, hãy đảm bảo rằng chuỗi bạn đang phân tích cú pháp ở múi giờ UTC vìtime.Time
4 chỉ là cách viết tắt củatime.Time
6 với ____42_______7 là một vị trí - khi bạn đang tạo một thời gian mới dựa trên một chuỗi có
time.Time
8, hãy đảm bảo rằng bạn tạo mộttime.Time
9 tương ứng với các giá trị trong chuỗi thời gian - khi so sánh xem một
time.Time
mà bạn đưa vào và lấy ra khỏi cơ sở dữ liệu có giống nhau hay không, hãy đảm bảo làm tròn đến giây gần nhất. Cột
2 không có độ phân giải để lưu trữ nano giây, vì vậy khi lấy ra cột đó sẽ bị mất và// connection is America/Phoenix db, _ := sql.Open["mysql", mysqlDSN] // table has an auto-increment id and a timestamp colum ts insert, _ := db.Prepare["INSERT INTO table [ts] VALUES [?]"] // ts is now 2020-10-07 12:00:00+01:00 for BST ts := time.Now[] results, _ := insert.Exec[ts] id, _ := results.LastInsertId[] // then we open another connection, this time the tz is Europe/London db2, _ := sql.Open["mysql", mysqlDSN2] select, _ := db.Prepare["SELECT * FROM table WHERE id = ?"] // we get the same row out that we inserted previously rows, _ := select.Exec[id] var id int64 var gotTime time.Time for rows.Next[] { _ = rows.Scan[&id, &gotTime] } // compare the times fmt.Printf["in: %s\nout: %s", ts.In[time.UTC].Format[time.RFC3339Nano], gotTime.In[time.UTC].Format[time.RFC3339Nano]] // this will print: in: 2020-10-07 11:00:00.703337Z out: 2020-10-07 11:00:00Z
.AddDate
2 sẽ không thành công¹ - nói chung hãy để Go api thực hiện công việc của nó khi hoạt động theo thời gian. Sử dụng các phương pháp có sẵn và chỉ loay hoay với múi giờ khi tạo thời gian hoặc khi bạn chuẩn bị hiển thị thời gian ở đâu đó
Hy vọng bạn tìm thấy điều này phần nào hữu ích. Nếu bạn có câu hỏi hoặc muốn gửi email cho tôi, hãy tìm tôi trên twitter qua @javorszky hoặc gửi email cho tôi trên gabor [at] javorszky [dot] co [dot] uk
phụ lục
[1] Về mặt kỹ thuật, bạn có thể tạo cột
// connection is America/Phoenix
db, _ := sql.Open["mysql", mysqlDSN]
// table has an auto-increment id and a timestamp colum ts
insert, _ := db.Prepare["INSERT INTO table [ts] VALUES [?]"]
// ts is now 2020-10-07 12:00:00+01:00 for BST
ts := time.Now[]
results, _ := insert.Exec[ts]
id, _ := results.LastInsertId[]
// then we open another connection, this time the tz is Europe/London
db2, _ := sql.Open["mysql", mysqlDSN2]
select, _ := db.Prepare["SELECT * FROM table WHERE id = ?"]
// we get the same row out that we inserted previously
rows, _ := select.Exec[id]
var id int64
var gotTime time.Time
for rows.Next[] {
_ = rows.Scan[&id, &gotTime]
}
// compare the times
fmt.Printf["in: %s\nout: %s",
ts.In[time.UTC].Format[time.RFC3339Nano],
gotTime.In[time.UTC].Format[time.RFC3339Nano]]
// this will print:
in: 2020-10-07 11:00:00.703337Z
out: 2020-10-07 11:00:00Z
2 hỗ trợ giây phân số lên đến 6 chữ số. Trong trường hợp đó, bạn vẫn cần phải .AddDate
4 để loại bỏ các vấn đề nano giây khi so sánh với .AddDate
5. Điều đó nói rằng việc sử dụng giây phân số và chế độ cắt ngắn trong SQL có thể gây ra sự trôi thời gian. Theo mặc định, khi MySQL nhận được một chuỗi .AddDate
6 được lưu trữ trong một cột có khả năng lấy giá trị 2 chữ số của giây phân số, nó sẽ lưu trữ .AddDate
7. Nếu chế độ cắt bớt được bật, phần phụ trang tương tự sẽ tạo ra .AddDate
8, điều này sẽ rất thú vị nếu bạn thực hiện .AddDate
9 và so sánh chúng vì chúng sẽ bị tắt trước .Round
0. Xem https. // nhà phát triển. mysql. com/doc/refman/8. 0/en/phân-giây. html để có thêm vài giây trong MySQL