Golang phân tích cú pháp mysql datetime

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ó

  • Golang phân tích cú pháp mysql datetime

Gabor Javorszky

Ngày 7 tháng 10 năm 2020 8 phút đọc

Golang phân tích cú pháp mysql datetime

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

  1. 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 đó
  2. 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.Truncate
  3. 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"
3

Nế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ống

const 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ống

Golang phân tích cú pháp mysql datetime
Màn hình cài đặt ngày & giờ trên máy Mac. Hiện được đặt thành Nagoya Nhật Bản

Cà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ó

Golang phân tích cú pháp mysql datetime
Một thư viện làm tôi nhớ đến một cơ sở dữ liệu

Đ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

  1. múi giờ của hệ thống, đó là những gì máy chủ mysql sẽ sử dụng
  2. 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"
3

má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ụng

TLDR 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à MySQL

như 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
8

Cù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)
1

Mú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)
6

Hã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.Time0

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.Time1) 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.Time3) 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.Time5) sẽ trả về một tập kết quả time.Time6 cốt lõi

Phương thức time.Time7 trên cấu trúc đó sẽ gọi một hàm có tên là time.Time8 cho mỗi cột, nơi nó sẽ lấy time.Time9, 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ên

Nế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.Time0, tại thời điểm đó bạn không thể quét nó thành biến time.Time

Golang phân tích cú pháp mysql datetime
Cầu vồng đôi. Nó có nghĩa là gì?

Đ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.Time4, 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.Time4 chỉ là cách viết tắt của time.Time6 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.Time8, hãy đảm bảo rằng bạn tạo một time.Time9 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
    // 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 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à .AddDate2 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 .AddDate4 để loại bỏ các vấn đề nano giây khi so sánh với .AddDate5. Đ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 .AddDate6 đượ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ữ .AddDate7. Nếu chế độ cắt bớt được bật, phần phụ trang tương tự sẽ tạo ra .AddDate8, điều này sẽ rất thú vị nếu bạn thực hiện .AddDate9 và so sánh chúng vì chúng sẽ bị tắt trước .Round0. 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

Làm cách nào để phân tích ngày tháng trong golang?

Khi phân tích cú pháp chuỗi Ngày trong Go, chúng ta có thể sử dụng hàm 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.

Làm thế nào để phân tích thời gian trong golang?

Hàm Parse() cho phép bạn phân tích cú pháp chuỗi ngày được định dạng và trả về giá trị thời gian được biểu thị bằng chuỗi . Hàm lấy bố cục và định dạng ngày được định dạng làm tham số. Sau đó nó trả về giá trị thời gian.