mirror of
https://github.com/johnkerl/miller.git
synced 2026-08-02 04:22:59 +00:00
port Miller fractional-second strftime format strings to Go
This commit is contained in:
parent
fe0bd4c8f4
commit
23c352ccfe
1 changed files with 81 additions and 3 deletions
|
|
@ -1,6 +1,8 @@
|
|||
package types
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"regexp"
|
||||
"time"
|
||||
|
||||
"github.com/lestrrat-go/strftime"
|
||||
|
|
@ -63,9 +65,12 @@ func MlrvalSec2GMTDate(input1 *Mlrval) *Mlrval {
|
|||
return MlrvalStrftime(input1, MlrvalPointerFromString("%Y-%m-%d"))
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// ================================================================
|
||||
// Argument 1 is int/float seconds since the epoch.
|
||||
// Argument 2 is format string like "%Y-%m-%d %H:%M:%S".
|
||||
|
||||
var extensionRegex = regexp.MustCompile("([1-9])S")
|
||||
|
||||
func MlrvalStrftime(input1, input2 *Mlrval) *Mlrval {
|
||||
epochSeconds, ok := input1.GetNumericToFloatValue()
|
||||
if !ok {
|
||||
|
|
@ -74,18 +79,90 @@ func MlrvalStrftime(input1, input2 *Mlrval) *Mlrval {
|
|||
if input2.mvtype != MT_STRING {
|
||||
return MLRVAL_ERROR
|
||||
}
|
||||
formatString := input2.printrep
|
||||
|
||||
// Convert argument1 from float seconds since the epoch to a Go time.
|
||||
inputTime := lib.EpochSecondsToTime(epochSeconds)
|
||||
|
||||
outputString, err := strftime.Format(formatString, inputTime)
|
||||
// Convert argument 2 to a strftime format string.
|
||||
//
|
||||
// Miller fractional-second formats are like "%6S", and were so in the C
|
||||
// implementation. However, in the strftime package we're using in the Go
|
||||
// port, extension-formats are only a single byte so we need to rewrite
|
||||
// them to "%6".
|
||||
formatString := extensionRegex.ReplaceAllString(input2.printrep, "$1")
|
||||
|
||||
formatter, err := strftime.New(formatString, strftimeExtensions)
|
||||
if err != nil {
|
||||
return MLRVAL_ERROR
|
||||
}
|
||||
|
||||
outputString := formatter.FormatString(inputTime)
|
||||
|
||||
return MlrvalPointerFromString(outputString)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// This is support for %1S .. %9S in format strings, using github.com/lestrrat-go/strftime.
|
||||
|
||||
var strftimeExtensions strftime.Option
|
||||
|
||||
// This is a helper function for the appenders below, which let people get
|
||||
// 1..9 decimal places in the seconds of their strftime format strings.
|
||||
func specificationHelper(b []byte, t time.Time, sprintfFormat string, quotient int) []byte {
|
||||
seconds := int(t.Second())
|
||||
fractional := int(t.Nanosecond() / quotient)
|
||||
secondsString := fmt.Sprintf("%02d", seconds)
|
||||
b = append(b, secondsString...)
|
||||
b = append(b, '.')
|
||||
fractionalString := fmt.Sprintf(sprintfFormat, fractional)
|
||||
b = append(b, fractionalString...)
|
||||
return b
|
||||
}
|
||||
|
||||
func init() {
|
||||
appender1 := strftime.AppendFunc(func(b []byte, t time.Time) []byte {
|
||||
return specificationHelper(b, t, "%01d", 100000000)
|
||||
})
|
||||
appender2 := strftime.AppendFunc(func(b []byte, t time.Time) []byte {
|
||||
return specificationHelper(b, t, "%02d", 10000000)
|
||||
})
|
||||
appender3 := strftime.AppendFunc(func(b []byte, t time.Time) []byte {
|
||||
return specificationHelper(b, t, "%03d", 1000000)
|
||||
})
|
||||
appender4 := strftime.AppendFunc(func(b []byte, t time.Time) []byte {
|
||||
return specificationHelper(b, t, "%04d", 100000)
|
||||
})
|
||||
appender5 := strftime.AppendFunc(func(b []byte, t time.Time) []byte {
|
||||
return specificationHelper(b, t, "%05d", 10000)
|
||||
})
|
||||
appender6 := strftime.AppendFunc(func(b []byte, t time.Time) []byte {
|
||||
return specificationHelper(b, t, "%06d", 1000)
|
||||
})
|
||||
appender7 := strftime.AppendFunc(func(b []byte, t time.Time) []byte {
|
||||
return specificationHelper(b, t, "%07d", 100)
|
||||
})
|
||||
appender8 := strftime.AppendFunc(func(b []byte, t time.Time) []byte {
|
||||
return specificationHelper(b, t, "%09d", 10)
|
||||
})
|
||||
appender9 := strftime.AppendFunc(func(b []byte, t time.Time) []byte {
|
||||
return specificationHelper(b, t, "%09d", 1)
|
||||
})
|
||||
|
||||
ss := strftime.NewSpecificationSet()
|
||||
ss.Set('1', appender1)
|
||||
ss.Set('2', appender2)
|
||||
ss.Set('3', appender3)
|
||||
ss.Set('4', appender4)
|
||||
ss.Set('5', appender5)
|
||||
ss.Set('6', appender6)
|
||||
ss.Set('7', appender7)
|
||||
ss.Set('8', appender8)
|
||||
ss.Set('9', appender9)
|
||||
|
||||
strftimeExtensions = strftime.WithSpecificationSet(ss)
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// Argument 1 is formatted date string like "2021-03-04 02:59:50".
|
||||
// Argument 2 is format string like "%Y-%m-%d %H:%M:%S".
|
||||
func MlrvalStrptime(input1, input2 *Mlrval) *Mlrval {
|
||||
|
|
@ -106,6 +183,7 @@ func MlrvalStrptime(input1, input2 *Mlrval) *Mlrval {
|
|||
return MlrvalPointerFromFloat64(float64(t.UnixNano()) / 1.0e9)
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// Argument 1 is formatted date string like "2021-03-04T02:59:50Z".
|
||||
func MlrvalGMT2Sec(input1 *Mlrval) *Mlrval {
|
||||
return MlrvalStrptime(input1, ptr_ISO8601_TIME_FORMAT)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue