سؤال

I'm trying to format a series a date such as:

  • March 12th, 2013, 3pm looks like : 2013-03-12-15.txt
  • March 12th, 2013, 4am looks like : 2013-03-12-4.txt

Using golang and the Time package

package main

import (
    "time"
    "fmt"
)

const layout = "2006-01-02-15.txt"

func main() {
    t := time.Date(2013, time.March, 12, 4, 0, 0, 0, time.UTC)
    fmt.Println(t.Format(layout))
}

Which unfortunately add a zero in front of the single-digit hour : 2013-03-12-04.txt

Is there an idiomatic way to reach the desired output, or I must tweak myself something with the String package ?

Thanks in advance for your help !

هل كانت مفيدة؟

المحلول

In case you need 24-hour format and don't want the leading zero for hour < 10 I only see a custom string format:

date := fmt.Sprintf("%d-%d-%d-%d", t.Year(), t.Month(), t.Day(), t.Hour())

Of course not an idiomatic way to format a date in Go.

Update (thanks for the comment):

t := time.Now() 
date := fmt.Sprintf("%s-%d.txt", t.Format("2006-01-02"), t.Hour())
fmt.Println(date)

نصائح أخرى

Use Time.Format only to format year/month and format the time yourself.

package main

import (
    "fmt"
    "time"
)

const layout = "2006-01-02-%d.txt"

func main() {
    t := time.Date(2013, time.March, 12, 4, 0, 0, 0, time.UTC)
    f := fmt.Sprintf(t.Format(layout), 4)

    fmt.Printf(f)
}

(Click to play)

You can see the number conversion table in the source code of format.go. Relevant part:

const (
// ...
    stdHour                  = iota + stdNeedClock // "15"
    stdHour12                                      // "3"
    stdZeroHour12                                  // "03"
// ...
)

There's no such thing as stdZeroHour, so no alternative behaviour for stdHour.

I added padding while I was formatting to get the desired leading 0's before any integer.

package main

import (
    "fmt"
    "time"
)

var TimeFormat string = "%04d-%02d-%02d %02d:%02d:%02d"

func main() {
    fmt.Printf(TimeFormat, time.Now().Year(), time.Now().Month(), time.Now().Day(), time.Now().Hour(), time.Now().Minute(), time.Now().Second())
}

It results in the following output

2022-07-13 18:41:50

resulting in the required leading 0's.

const (
       H12Format = "2006/1/2/3/4.txt"
       H24Format = "2006/1/2/15/4.txt"
   )    
   func path(date time.Time) string {
    if date.Hour() < 10 {
        return date.Format(H12Format)
    }
    return date.Format(H24Format)
   }

Unfortunately the go playground doesn't allow running tests and benchmarks.

The following code contain the previous solutions and mine with benchmark.

On my computer these are the result:

BenchmarkA-4     5000000               293 ns/op              32 B/op          1 allocs/op
BenchmarkB-4     5000000               380 ns/op              48 B/op          2 allocs/op
BenchmarkC-4     3000000               448 ns/op              56 B/op          4 allocs/op

To test it yourself copy the code locally and run it: go test -benchmem -run=XXX -bench=Benchmark

package format

import (
    "fmt"
    "testing"
    "time"
)

const (
    layout    = "2006-01-02-3.txt"
    layoutd   = "2006-01-02-%d.txt"
    H12Format = "2006/1/2/3/4.txt"
    H24Format = "2006/1/2/15/4.txt"
)

func BenchmarkA(b *testing.B) {
    for n := 0; n < b.N; n++ {
        path(time.Now())
    }
}

func BenchmarkB(b *testing.B) {
    for n := 0; n < b.N; n++ {
        fmtpath(time.Now())
    }
}

func BenchmarkC(b *testing.B) {
    for n := 0; n < b.N; n++ {
        longpath(time.Now())
    }
}
func path(date time.Time) string {
    if date.Hour() < 10 {
        return date.Format(H12Format)
    }
    return date.Format(H24Format)
}

func fmtpath(date time.Time) string {
    return fmt.Sprintf(date.Format(layoutd), 4)
}

func longpath(date time.Time) string {
    return fmt.Sprintf("%s-%d.txt", date.Format("2006-01-02"), date.Hour())
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top