Go / golang time.Now (). UnixNano () chuyển đổi sang mili giây?


83

Tôi làm cách nào để có được thời gian Unix trong Go tính bằng mili giây?

Tôi có chức năng sau:

func makeTimestamp() int64 {
    return time.Now().UnixNano() % 1e6 / 1e3
}

Tôi cần ít độ chính xác hơn và chỉ muốn mili giây.

Câu trả lời:


130

Chỉ cần chia nó:

func makeTimestamp() int64 {
    return time.Now().UnixNano() / int64(time.Millisecond)
}

Đây là một ví dụ mà bạn có thể biên dịch và chạy để xem đầu ra

package main

import (
    "time"
    "fmt"
)

func main() {
    a := makeTimestamp()

    fmt.Printf("%d \n", a)
}

func makeTimestamp() int64 {
    return time.Now().UnixNano() / int64(time.Millisecond)
}

39
Tính toán trên không thực sự có ý nghĩa. Bạn không chia nano giây cho mili giây. Tình cờ xảy ra trường hợp golang biểu thị thời gian xuống dưới nano giây và hằng số 'Mili giây' là 1.000.000. Nói về mặt toán học, tính toán nên là: time.Now().UnixNano() * (time.Nanosecond / time.Millisecond). Tuy nhiên, tốt nhất là thay đổi thứ tự vì phép chia số nguyên:time.Nanosecond * time.Now().UnixNano() / time.Millisecond
Jonno

4
cảm ơn vì điều đó. Bạn có thể tin tưởng vào sự đảm bảo đó, nhưng thực tế đây là lỗi Y2K. Nó có thể vỡ vào một thời điểm nào đó trong tương lai. Tại sao chọn biểu diễn toán học sai?
Jonno

2
chúng là các hằng số tùy ý. Chúng có thể thay đổi trong tương lai. Gói thời gian hiện "hoạt động" ở độ chính xác nano giây, nhưng đó là lựa chọn tùy ý dẫn đến thời gian thiết lập.Millisecond = 1.000.000. Lưu ý rằng ngay cả trong cùng một tệp mà bạn đã tham chiếu, time.Milisecond được đặt thành 1000 * Microsecond, bởi vì nói theo toán học thì đó là những gì nó nên đại diện. Tôi đang ngoại tuyến - Hy vọng lời giải thích của tôi sẽ giúp ích
Jonno

10
-1 Điều này chỉ là sai. Đơn vị của bạn không cộng lại. Tra cứu phân tích chiều từ vật lý. Kết quả của bạn không đại diện cho thời gian.
Kugel

7
Câu trả lời nhanh chóng cho những người bận rộn. Nhìn vào https://gobyexample.com/epoch
honzajde

63

Như @Jono đã chỉ ra trong câu trả lời của @ OneOfOne, câu trả lời đúng phải tính đến thời lượng một nano giây. Ví dụ:

func makeTimestamp() int64 {
    return time.Now().UnixNano() / (int64(time.Millisecond)/int64(time.Nanosecond))
}

Câu trả lời của OneOfOne hoạt động vì time.Nanosecondxảy ra 1và chia cho 1 không có hiệu lực. Tôi không biết đủ về go để biết khả năng điều này sẽ thay đổi như thế nào trong tương lai, nhưng để có câu trả lời chính xác, tôi sẽ sử dụng chức năng này, không phải câu trả lời của OneOfOne. Tôi nghi ngờ có bất kỳ nhược điểm nào về hiệu suất vì trình biên dịch sẽ có thể tối ưu hóa điều này một cách hoàn hảo.

Xem https://en.wikipedia.org/wiki/Dimensional_analysis

Một cách khác để xem xét điều này là cả hai time.Now().UnixNano()time.Millisecondsử dụng cùng một đơn vị (Nanoseconds). Miễn là điều đó đúng, câu trả lời của OneOfOne sẽ hoạt động hoàn toàn tốt.


4
Giá trị của .UnixNano()sẽ luôn là thời gian tính bằng Nanoseconds, time.Millisecondsẽ luôn là giá trị của bạn, bạn đoán nó, một mili giây, vì vậy ngay cả khi vì bất kỳ lý do ngu ngốc nào mà giá trị không đổi thay đổi, chia UnixNano cho Milisecond sẽ luôn trả về giá trị bằng mili giây.
OneOfOne

9
Các đơn vị của Unix.Nano không được đề cập; cũng không phải là giá trị của thời gian. Những gì được đề cập là đơn vị thời gian. 1 giây. Nó tình cờ được xác định bằng nano giây, đó là lý do tại sao câu trả lời của bạn hoạt động. Nếu time.Milliseconds được đo bằng các đơn vị khác (ví dụ, micro giây), câu trả lời bạn đưa ra sẽ không hoạt động.
Bjorn Roche

2
@BjornRoche Tôi đến bữa tiệc này hơi muộn, nhưng câu trả lời không phải là đúng (int64(time.Now().UnixNano() / int64(time.Nanosecond))/int64(time.Millisecond)sao? Phân tích chiều ns/(ms/ns)trả về ns^2/ms. Câu trả lời của bạn cũng làm việc vì time.Nanosecond=1, nhưng các đơn vị đang tắt ...
Các Puma

1
@thepuma Đã lâu rồi nên tôi có thể nhìn nhầm hoặc hiểu sai ý bạn, nhưng ns / (ms / ns) tương đương với ns ^ 2 / ms, vì vậy cả hai câu trả lời đều hoạt động.
Bjorn Roche

Câu trả lời này là đúng vì chạy này sẽ hiển thị kết quả tương tự như khi chuyển đổi sử dụng bộ chuyển đổi trực tuyến unitconverters.net/prefixes/nano-to-milli.htm
user666

55

Giữ nó đơn giản.

func NowAsUnixMilli() int64 {
    return time.Now().UnixNano() / 1e6
}

2

Tôi nghĩ tốt hơn nên làm tròn thời gian đến mili giây trước khi phân chia.

func makeTimestamp() int64 {
    return time.Now().Round(time.Millisecond).UnixNano() / (int64(time.Millisecond)/int64(time.Nanosecond))
}

Đây là một chương trình ví dụ:

package main

import (
        "fmt"
        "time"
)

func main() {
        fmt.Println(unixMilli(time.Unix(0, 123400000)))
        fmt.Println(unixMilli(time.Unix(0, 123500000)))
        m := makeTimestampMilli()
        fmt.Println(m)
        fmt.Println(time.Unix(m/1e3, (m%1e3)*int64(time.Millisecond)/int64(time.Nanosecond)))
}

func unixMilli(t time.Time) int64 {
        return t.Round(time.Millisecond).UnixNano() / (int64(time.Millisecond) / int64(time.Nanosecond))
}

func makeTimestampMilli() int64 {
        return unixMilli(time.Now())
}

Chương trình trên đã in kết quả dưới đây trên máy của tôi:

123
124
1472313624305
2016-08-28 01:00:24.305 +0900 JST

Bạn đã quên đề cập đến lý do tại sao bạn nghĩ tốt hơn nên làm tròn thời gian thành mili giây.
Gurpartap Singh

1

Giải pháp đọc đơn giản nhưng chính xác sẽ là:

func nowAsUnixMilliseconds(){
    return time.Now().Round(time.Millisecond).UnixNano() / 1e6
}

Chức năng này:

  1. Làm tròn chính xác giá trị đến mili giây gần nhất (so sánh với phép chia số nguyên: nó chỉ loại bỏ phần thập phân của giá trị kết quả);
  2. Không đi sâu vào các chi tiết cụ thể của Go về thời gian. Cưỡng chế bão hòa - vì nó sử dụng một hằng số đại diện cho bộ chia mili giây / nano giây tuyệt đối.

PS Tôi đã chạy các điểm chuẩn với các bộ chia liên tục và tổng hợp, chúng hầu như không có sự khác biệt, vì vậy hãy thoải mái sử dụng giải pháp dễ đọc hơn hoặc nghiêm ngặt hơn về ngôn ngữ.


Nếu bạn muốn biết thời gian Unix chính xác tính bằng mili giây (mili giây kể từ Kỷ nguyên), bạn không nên sử dụng Round (), vì điều đó sẽ làm tròn một nửa thời gian và kết quả của bạn sau đó sẽ chứa một mili giây chưa trôi hết.
torbenl

Cảm ơn bạn đã lưu ý, @torbenl - điều này có thể quan trọng đối với hầu hết các hệ thống (của tôi là loại trừ, thời gian này chỉ được lưu trữ cho lịch sử).
Liubov
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.