Go 的快速 strftime
f , err := strftime . New ( `.... pattern ...` )
if err := f . Format ( buf , time . Now ()); err != nil {
log . Println ( err . Error ())
}
該庫的目標是
取得模式和時間,並格式化它。該函數是一個實用函數,每次呼叫函數時都會重新編譯模式。如果您事先知道將多次格式化相同的模式,請考慮使用New
建立Strftime
物件並重複使用它。
採用該模式並建立一個新的Strftime
物件。
傳回用於建立此Strftime
物件的模式字串
根據預先編譯的模式格式化時間,並將結果寫入指定的io.Writer
根據預編譯模式格式化時間,並傳回結果字串。
圖案 | 描述 |
---|---|
%一個 | 完整工作日名稱的國家代表性 |
%一個 | 縮寫工作日的全國代表性 |
%B | 完整月份名稱的國家代表 |
%b | 縮寫月份名稱的國家表示 |
%C | (年/100)作為十進制數;個位數前面有一個零 |
%c | 時間和日期的國家表示 |
%D | 相當於%m/%d/%y |
%d | 十進制數形式的月份日期 (01-31) |
%e | 以十進制數表示的月份日期 (1-31);個位數前面有一個空格 |
%F | 相當於%Y-%m-%d |
%H | 十進制數 (00-23) 形式的小時(24 小時制) |
%h | 與%b相同 |
%我 | 十進制數形式的小時(12 小時制)(01-12) |
%j | 十進制數形式的一年中的第幾天 (001-366) |
%k | 十進制數 (0-23) 形式的小時(24 小時制);個位數前面有一個空格 |
%l | 十進制數 (1-12) 形式的小時(12 小時制);個位數前面有一個空格 |
%M | 十進制數形式的分鐘 (00-59) |
%m | 十進制數形式的月份 (01-12) |
%n | 換行符 |
%p | 酌情「午前」(am) 或「午後」(pm) 的國家代表性。 |
%R | 相當於%H:%M |
%r | 相當於 %I:%M:%S %p |
%S | 第二個十進制數 (00-60) |
%T | 相當於 %H:%M:%S |
%t | 一個選項卡 |
%U | 一年中的週數(星期日為一週的第一天),十進制數 (00-53) |
%u | 工作日(星期一為一週的第一天)十進制數 (1-7) |
%V | 一年中的週數(星期一為一週的第一天),十進制數 (01-53) |
%v | 相當於%e-%b-%Y |
%W | 一年中的週數(星期一為一週的第一天),十進制數 (00-53) |
%w | 工作日(星期日為一週的第一天)十進制數 (0-6) |
%X | 當時的國家代表 |
%x | 日期的國家代表 |
%Y | 以十進制數表示的年份 |
%y | 不帶世紀的十進制年份 (00-99) |
%Z | 時區名稱 |
%z | 與 UTC 的時區偏移量 |
%% | 一個“%” |
該程式庫通常會嘗試相容 POSIX,但有時您只需要一兩個相對廣泛使用但未包含在 POSIX 規範中的額外規範。
例如,POSIX 沒有指定如何列印毫秒,但流行的實作允許%f
或%L
來實現這一點。
對於這些實例, strftime.Strftime
可以配置為使用一組自訂規範:
ss := strftime.NewSpecificationSet()
ss.Set('L', ...) // provide implementation for `%L`
// pass this new specification set to the strftime instance
p, err := strftime.New(`%L`, strftime.WithSpecificationSet(ss))
p.Format(..., time.Now())
實作必須實作Appender
接口,即
type Appender interface {
Append([]byte, time.Time) []byte
}
對於常用的擴充功能(例如毫秒範例和 Unix 時間戳記),我們提供了預設實現,以便使用者可以執行以下操作之一:
// (1) Pass a specification byte and the Appender
// This allows you to pass arbitrary Appenders
p, err := strftime.New(
`%L`,
strftime.WithSpecification('L', strftime.Milliseconds),
)
// (2) Pass an option that knows to use strftime.Milliseconds
p, err := strftime.New(
`%L`,
strftime.WithMilliseconds('L'),
)
對於 Unix 時間戳也是如此:
// (1) Pass a specification byte and the Appender
// This allows you to pass arbitrary Appenders
p, err := strftime.New(
`%s`,
strftime.WithSpecification('s', strftime.UnixSeconds),
)
// (2) Pass an option that knows to use strftime.UnixSeconds
p, err := strftime.New(
`%s`,
strftime.WithUnixSeconds('s'),
)
如果缺少通用規範,請隨時提交 PR(但請務必能夠捍衛它的「通用性」)
Milliseconds
(相關選項: WithMilliseconds
);
Microseconds
(相關選項: WithMicroseconds
);
UnixSeconds
(相關選項: WithUnixSeconds
)。
以下基準測試是單獨運行的,因為一些庫在特定平台上使用 cgo(值得注意的是,快速版本)
// On my OS X 10.14.6, 2.3 GHz Intel Core i5, 16GB memory.
// go version go1.13.4 darwin/amd64
hummingbird% go test -tags bench -benchmem -bench .
<snip>
BenchmarkTebeka-4 297471 3905 ns/op 257 B/op 20 allocs/op
BenchmarkJehiah-4 818444 1773 ns/op 256 B/op 17 allocs/op
BenchmarkFastly-4 2330794 550 ns/op 80 B/op 5 allocs/op
BenchmarkLestrrat-4 916365 1458 ns/op 80 B/op 2 allocs/op
BenchmarkLestrratCachedString-4 2527428 546 ns/op 128 B/op 2 allocs/op
BenchmarkLestrratCachedWriter-4 537422 2155 ns/op 192 B/op 3 allocs/op
PASS
ok github.com/lestrrat-go/strftime 25.618s
// On a host on Google Cloud Platform, machine-type: f1-micro (vCPU x 1, memory: 0.6GB)
// (Yes, I was being skimpy)
// Linux <snip> 4.9.0-11-amd64 #1 SMP Debian 4.9.189-3+deb9u1 (2019-09-20) x86_64 GNU/Linux
// go version go1.13.4 linux/amd64
hummingbird% go test -tags bench -benchmem -bench .
<snip>
BenchmarkTebeka 254997 4726 ns/op 256 B/op 20 allocs/op
BenchmarkJehiah 659289 1882 ns/op 256 B/op 17 allocs/op
BenchmarkFastly 389150 3044 ns/op 224 B/op 13 allocs/op
BenchmarkLestrrat 699069 1780 ns/op 80 B/op 2 allocs/op
BenchmarkLestrratCachedString 2081594 589 ns/op 128 B/op 2 allocs/op
BenchmarkLestrratCachedWriter 825763 1480 ns/op 192 B/op 3 allocs/op
PASS
ok github.com/lestrrat-go/strftime 11.355s
如果您可以重複使用格式模式,則該程式庫比其他程式庫快得多。
這是基準測試結果的註釋清單。您可以清楚地看到,(重新)使用Strftime
物件並產生字串是最快的。寫入io.Writer
似乎有點緩慢,但由於生成字串的人正在做幾乎完全相同的事情,我們相信這純粹是寫入io.Writer
的開銷
導入路徑 | 分數 | 筆記 |
---|---|---|
github.com/lestrrat-go/strftime | 300萬 | 使用FormatString() (快取) |
github.com/fastly/go-utils/strftime | 2000000 | OS X 上的純 go 版本 |
github.com/lestrrat-go/strftime | 1000000 | 使用Format() (不緩存) |
github.com/jehiah/go-strftime | 1000000 | |
github.com/fastly/go-utils/strftime | 1000000 | Linux 上的 cgo 版本 |
github.com/lestrrat-go/strftime | 50萬 | 使用Format() (快取) |
github.com/tebeka/strftime | 30萬 |
但是,根據您的模式,此速度可能會有所不同。如果您發現某個特定模式似乎運行緩慢,請發送補丁或測試。
另請注意,此基準測試僅使用所有比較庫支援的轉換規範子集。
將來進行效能比較時需要考慮的事項:
%specification
?