mirror of
https://github.com/johnkerl/miller.git
synced 2026-01-23 02:14:13 +00:00
* Update package version * Update makefile targets * Update readme packages * Remaining old packages via rg/sd
616 lines
18 KiB
Go
616 lines
18 KiB
Go
package bifs
|
|
|
|
import (
|
|
"fmt"
|
|
"regexp"
|
|
"time"
|
|
|
|
strptime "github.com/johnkerl/miller/v6/pkg/pbnjay-strptime"
|
|
"github.com/lestrrat-go/strftime"
|
|
|
|
"github.com/johnkerl/miller/v6/pkg/lib"
|
|
"github.com/johnkerl/miller/v6/pkg/mlrval"
|
|
)
|
|
|
|
const ISO8601_TIME_FORMAT = "%Y-%m-%dT%H:%M:%SZ"
|
|
|
|
var ptr_ISO8601_TIME_FORMAT = mlrval.FromString("%Y-%m-%dT%H:%M:%SZ")
|
|
var ptr_ISO8601_LOCAL_TIME_FORMAT = mlrval.FromString("%Y-%m-%d %H:%M:%S")
|
|
var ptr_YMD_FORMAT = mlrval.FromString("%Y-%m-%d")
|
|
|
|
// ================================================================
|
|
func BIF_systime() *mlrval.Mlrval {
|
|
return mlrval.FromFloat(
|
|
float64(time.Now().UnixNano()) / 1.0e9,
|
|
)
|
|
}
|
|
func BIF_systimeint() *mlrval.Mlrval {
|
|
return mlrval.FromInt(time.Now().Unix())
|
|
}
|
|
|
|
func BIF_sysntime() *mlrval.Mlrval {
|
|
return mlrval.FromInt(time.Now().UnixNano())
|
|
}
|
|
|
|
var startTime float64
|
|
var startNTime int64
|
|
|
|
func init() {
|
|
startTime = float64(time.Now().UnixNano()) / 1.0e9
|
|
startNTime = time.Now().UnixNano()
|
|
}
|
|
func BIF_uptime() *mlrval.Mlrval {
|
|
return mlrval.FromFloat(
|
|
float64(time.Now().UnixNano())/1.0e9 - startTime,
|
|
)
|
|
}
|
|
func BIF_upntime() *mlrval.Mlrval {
|
|
return mlrval.FromInt(
|
|
time.Now().UnixNano() - startNTime,
|
|
)
|
|
}
|
|
|
|
// ================================================================
|
|
|
|
func BIF_sec2gmt_unary(input1 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
floatValue, isNumeric := input1.GetNumericToFloatValue()
|
|
if !isNumeric {
|
|
return input1
|
|
}
|
|
numDecimalPlaces := 0
|
|
return mlrval.FromString(lib.Sec2GMT(floatValue, numDecimalPlaces))
|
|
}
|
|
|
|
func BIF_nsec2gmt_unary(input1 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
intValue, errValue := input1.GetIntValueOrError("nsec2gmt")
|
|
if errValue != nil {
|
|
return errValue
|
|
}
|
|
numDecimalPlaces := 0
|
|
return mlrval.FromString(lib.Nsec2GMT(intValue, numDecimalPlaces))
|
|
}
|
|
|
|
func BIF_sec2gmt_binary(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
floatValue, errValue := input1.GetNumericToFloatValueOrError("sec2gmt")
|
|
if errValue != nil {
|
|
return errValue
|
|
}
|
|
numDecimalPlaces, errValue := input2.GetIntValueOrError("sec2gmt")
|
|
if errValue != nil {
|
|
return errValue
|
|
}
|
|
return mlrval.FromString(lib.Sec2GMT(floatValue, int(numDecimalPlaces)))
|
|
}
|
|
|
|
func BIF_nsec2gmt_binary(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
intValue, ok := input1.GetIntValue()
|
|
if !ok {
|
|
return input1
|
|
}
|
|
numDecimalPlaces, errValue := input2.GetIntValueOrError("nsec2gmt")
|
|
if errValue != nil {
|
|
return errValue
|
|
}
|
|
return mlrval.FromString(lib.Nsec2GMT(intValue, int(numDecimalPlaces)))
|
|
}
|
|
|
|
func BIF_sec2localtime_unary(input1 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
floatValue, isNumeric := input1.GetNumericToFloatValue()
|
|
if !isNumeric {
|
|
return input1
|
|
}
|
|
numDecimalPlaces := 0
|
|
return mlrval.FromString(lib.Sec2LocalTime(floatValue, numDecimalPlaces))
|
|
}
|
|
|
|
func BIF_nsec2localtime_unary(input1 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
intValue, ok := input1.GetIntValue()
|
|
if !ok {
|
|
return input1
|
|
}
|
|
numDecimalPlaces := 0
|
|
return mlrval.FromString(lib.Nsec2LocalTime(intValue, numDecimalPlaces))
|
|
}
|
|
|
|
func BIF_sec2localtime_binary(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
floatValue, isNumeric := input1.GetNumericToFloatValue()
|
|
if !isNumeric {
|
|
return input1
|
|
}
|
|
numDecimalPlaces, errValue := input2.GetIntValueOrError("sec2localtime")
|
|
if errValue != nil {
|
|
return errValue
|
|
}
|
|
return mlrval.FromString(lib.Sec2LocalTime(floatValue, int(numDecimalPlaces)))
|
|
}
|
|
|
|
func BIF_nsec2localtime_binary(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
intValue, ok := input1.GetIntValue()
|
|
if !ok {
|
|
return input1
|
|
}
|
|
numDecimalPlaces, errValue := input2.GetIntValueOrError("nsec2localtime")
|
|
if errValue != nil {
|
|
return errValue
|
|
}
|
|
return mlrval.FromString(lib.Nsec2LocalTime(intValue, int(numDecimalPlaces)))
|
|
}
|
|
|
|
func BIF_sec2localtime_ternary(input1, input2, input3 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
floatValue, isNumeric := input1.GetNumericToFloatValue()
|
|
if !isNumeric {
|
|
return input1
|
|
}
|
|
numDecimalPlaces, errValue := input2.GetIntValueOrError("sec2localtime")
|
|
if errValue != nil {
|
|
return errValue
|
|
}
|
|
locationString, errValue := input3.GetStringValueOrError("sec2localtime")
|
|
if errValue != nil {
|
|
return errValue
|
|
}
|
|
location, err := time.LoadLocation(locationString)
|
|
if err != nil {
|
|
return mlrval.FromError(err)
|
|
}
|
|
return mlrval.FromString(lib.Sec2LocationTime(floatValue, int(numDecimalPlaces), location))
|
|
}
|
|
|
|
func BIF_nsec2localtime_ternary(input1, input2, input3 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
intValue, isNumeric := input1.GetIntValue()
|
|
if !isNumeric {
|
|
return input1
|
|
}
|
|
numDecimalPlaces, errValue := input2.GetIntValueOrError("nsec2localtime")
|
|
if errValue != nil {
|
|
return errValue
|
|
}
|
|
locationString, errValue := input3.GetStringValueOrError("nsec2localtime")
|
|
if errValue != nil {
|
|
return errValue
|
|
}
|
|
location, err := time.LoadLocation(locationString)
|
|
if err != nil {
|
|
return mlrval.FromError(err)
|
|
}
|
|
return mlrval.FromString(lib.Nsec2LocationTime(intValue, int(numDecimalPlaces), location))
|
|
}
|
|
|
|
func BIF_sec2gmtdate(input1 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
if !input1.IsNumeric() {
|
|
return input1
|
|
}
|
|
return BIF_strftime(input1, ptr_YMD_FORMAT)
|
|
}
|
|
|
|
func BIF_nsec2gmtdate(input1 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
if !input1.IsNumeric() {
|
|
return input1
|
|
}
|
|
return BIF_strfntime(input1, ptr_YMD_FORMAT)
|
|
}
|
|
|
|
func BIF_sec2localdate_unary(input1 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
if !input1.IsNumeric() {
|
|
return input1
|
|
}
|
|
return BIF_strftime_local_binary(input1, ptr_YMD_FORMAT)
|
|
}
|
|
|
|
func BIF_nsec2localdate_unary(input1 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
if !input1.IsNumeric() {
|
|
return input1
|
|
}
|
|
return BIF_strfntime_local_binary(input1, ptr_YMD_FORMAT)
|
|
}
|
|
|
|
func BIF_sec2localdate_binary(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
if !input1.IsNumeric() {
|
|
return input1
|
|
}
|
|
return BIF_strftime_local_ternary(input1, ptr_YMD_FORMAT, input2)
|
|
}
|
|
|
|
func BIF_nsec2localdate_binary(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
if !input1.IsNumeric() {
|
|
return input1
|
|
}
|
|
return BIF_strfntime_local_ternary(input1, ptr_YMD_FORMAT, input2)
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
func BIF_localtime2gmt_unary(input1 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
if !input1.IsString() {
|
|
return mlrval.FromNotStringError("localtime2gmt", input1)
|
|
}
|
|
return BIF_nsec2gmt_unary(BIF_localtime2nsec_unary(input1))
|
|
}
|
|
|
|
func BIF_localtime2gmt_binary(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
if !input1.IsString() {
|
|
return mlrval.FromNotStringError("localtime2gmt", input1)
|
|
}
|
|
return BIF_nsec2gmt_unary(BIF_localtime2nsec_binary(input1, input2))
|
|
}
|
|
|
|
func BIF_gmt2localtime_unary(input1 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
if !input1.IsString() {
|
|
return mlrval.FromNotStringError("gmt2localtime2", input1)
|
|
}
|
|
return BIF_nsec2localtime_unary(BIF_gmt2nsec(input1))
|
|
}
|
|
|
|
func BIF_gmt2localtime_binary(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
if !input1.IsString() {
|
|
return mlrval.FromNotStringError("gmt2localtime2", input1)
|
|
}
|
|
return BIF_nsec2localtime_ternary(BIF_gmt2nsec(input1), mlrval.FromInt(0), input2)
|
|
}
|
|
|
|
// ================================================================
|
|
// 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 BIF_strftime(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
return strftimeHelper(input1, input2, false, nil, "strftime")
|
|
}
|
|
|
|
func BIF_strfntime(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
return strfntimeHelper(input1, input2, false, nil, "strfntime")
|
|
}
|
|
|
|
func BIF_strftime_local_binary(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
return strftimeHelper(input1, input2, true, nil, "strftime_local")
|
|
}
|
|
|
|
func BIF_strfntime_local_binary(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
return strfntimeHelper(input1, input2, true, nil, "strfntime_local")
|
|
}
|
|
|
|
func BIF_strftime_local_ternary(input1, input2, input3 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
locationString, errValue := input3.GetStringValueOrError("strftime")
|
|
if errValue != nil {
|
|
return errValue
|
|
}
|
|
|
|
location, err := time.LoadLocation(locationString)
|
|
if err != nil {
|
|
return mlrval.FromError(err)
|
|
}
|
|
|
|
return strftimeHelper(input1, input2, true, location, "strftime_local")
|
|
}
|
|
|
|
func BIF_strfntime_local_ternary(input1, input2, input3 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
locationString, errValue := input3.GetStringValueOrError("strfntime")
|
|
if errValue != nil {
|
|
return errValue
|
|
}
|
|
location, err := time.LoadLocation(locationString)
|
|
if err != nil {
|
|
return mlrval.FromError(err)
|
|
}
|
|
return strfntimeHelper(input1, input2, true, location, "strfntime_local")
|
|
}
|
|
|
|
func strftimeHelper(
|
|
input1, input2 *mlrval.Mlrval,
|
|
doLocal bool,
|
|
location *time.Location,
|
|
funcname string,
|
|
) *mlrval.Mlrval {
|
|
if input1.IsVoid() {
|
|
return input1
|
|
}
|
|
epochSeconds, errValue := input1.GetNumericToFloatValueOrError(funcname)
|
|
if errValue != nil {
|
|
return errValue
|
|
}
|
|
if !input2.IsString() {
|
|
return mlrval.FromNotStringError(funcname, input2)
|
|
}
|
|
|
|
// Convert argument1 from float seconds since the epoch to a Go time.
|
|
var inputTime time.Time
|
|
if doLocal {
|
|
if location != nil {
|
|
inputTime = lib.EpochSecondsToLocationTime(epochSeconds, location)
|
|
} else {
|
|
inputTime = lib.EpochSecondsToLocalTime(epochSeconds)
|
|
}
|
|
} else {
|
|
inputTime = lib.EpochSecondsToGMT(epochSeconds)
|
|
}
|
|
|
|
// 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.AcquireStringValue(), "$1")
|
|
|
|
formatter, err := strftime.New(formatString, strftimeExtensions)
|
|
if err != nil {
|
|
return mlrval.FromError(err)
|
|
}
|
|
|
|
outputString := formatter.FormatString(inputTime)
|
|
|
|
return mlrval.FromString(outputString)
|
|
}
|
|
|
|
func strfntimeHelper(
|
|
input1, input2 *mlrval.Mlrval,
|
|
doLocal bool,
|
|
location *time.Location,
|
|
funcname string,
|
|
) *mlrval.Mlrval {
|
|
if input1.IsVoid() {
|
|
return input1
|
|
}
|
|
epochNanoseconds, errValue := input1.GetIntValueOrError(funcname)
|
|
if errValue != nil {
|
|
return errValue
|
|
}
|
|
if !input2.IsString() {
|
|
return mlrval.FromNotStringError(funcname, input2)
|
|
}
|
|
|
|
// Convert argument1 from float seconds since the epoch to a Go time.
|
|
var inputTime time.Time
|
|
if doLocal {
|
|
if location != nil {
|
|
inputTime = lib.EpochNanosecondsToLocationTime(epochNanoseconds, location)
|
|
} else {
|
|
inputTime = lib.EpochNanosecondsToLocalTime(epochNanoseconds)
|
|
}
|
|
} else {
|
|
inputTime = lib.EpochNanosecondsToGMT(epochNanoseconds)
|
|
}
|
|
|
|
// Convert argument 2 to a strfntime format string.
|
|
//
|
|
// Miller fractional-second formats are like "%6S", and were so in the C
|
|
// implementation. However, in the strfntime 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.AcquireStringValue(), "$1")
|
|
|
|
formatter, err := strftime.New(formatString, strftimeExtensions)
|
|
if err != nil {
|
|
return mlrval.FromError(err)
|
|
}
|
|
|
|
outputString := formatter.FormatString(inputTime)
|
|
|
|
return mlrval.FromString(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)
|
|
})
|
|
appenderN := strftime.AppendFunc(func(b []byte, t time.Time) []byte {
|
|
nanos := int(t.Nanosecond())
|
|
s := fmt.Sprintf("%09d", nanos)
|
|
//return append(b, []byte(s))
|
|
return append(b, s...)
|
|
})
|
|
appenderO := strftime.AppendFunc(func(b []byte, t time.Time) []byte {
|
|
nanos := int(t.Nanosecond())
|
|
s := fmt.Sprintf("%d", nanos)
|
|
//return append(b, []byte(s))
|
|
return append(b, s...)
|
|
})
|
|
appenderS := strftime.AppendFunc(func(b []byte, t time.Time) []byte {
|
|
epochSeconds := t.Unix()
|
|
s := fmt.Sprintf("%d", epochSeconds)
|
|
return append(b, s...)
|
|
})
|
|
|
|
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)
|
|
ss.Set('N', appenderN)
|
|
ss.Set('O', appenderO)
|
|
ss.Set('s', appenderS)
|
|
|
|
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 BIF_strptime(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
return bif_strptime_unary_aux(input1, input2, false, false)
|
|
}
|
|
|
|
func BIF_strpntime(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
return bif_strptime_unary_aux(input1, input2, false, true)
|
|
}
|
|
|
|
func bif_strptime_unary_aux(input1, input2 *mlrval.Mlrval, doLocal, produceNanoseconds bool) *mlrval.Mlrval {
|
|
if !input1.IsString() {
|
|
return mlrval.FromNotStringError("strptime", input1)
|
|
}
|
|
if !input2.IsString() {
|
|
return mlrval.FromNotStringError("strptime", input2)
|
|
}
|
|
timeString := input1.AcquireStringValue()
|
|
formatString := input2.AcquireStringValue()
|
|
|
|
var t time.Time
|
|
var err error
|
|
if doLocal {
|
|
t, err = strptime.ParseLocal(timeString, formatString)
|
|
} else {
|
|
t, err = strptime.Parse(timeString, formatString)
|
|
}
|
|
if err != nil {
|
|
return mlrval.FromError(err)
|
|
}
|
|
|
|
if produceNanoseconds {
|
|
return mlrval.FromInt(t.UnixNano())
|
|
} else {
|
|
return mlrval.FromFloat(float64(t.UnixNano()) / 1.0e9)
|
|
}
|
|
}
|
|
|
|
// Argument 1 is formatted date string like "2021-03-04T02:59:50Z".
|
|
func BIF_gmt2sec(input1 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
return bif_strptime_unary_aux(input1, ptr_ISO8601_TIME_FORMAT, false, false)
|
|
}
|
|
|
|
// Argument 1 is formatted date string like "2021-03-04T02:59:50Z".
|
|
func BIF_gmt2nsec(input1 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
return bif_strptime_unary_aux(input1, ptr_ISO8601_TIME_FORMAT, false, true)
|
|
}
|
|
|
|
func BIF_localtime2sec_unary(input1 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
return bif_strptime_unary_aux(input1, ptr_ISO8601_LOCAL_TIME_FORMAT, true, false)
|
|
}
|
|
|
|
func BIF_localtime2nsec_unary(input1 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
return bif_strptime_unary_aux(input1, ptr_ISO8601_LOCAL_TIME_FORMAT, true, true)
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
func BIF_strptime_local_binary(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
return bif_strptime_binary_aux(input1, input2, true, false)
|
|
}
|
|
|
|
func BIF_strpntime_local_binary(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
return bif_strptime_binary_aux(input1, input2, true, true)
|
|
}
|
|
|
|
func bif_strptime_binary_aux(input1, input2 *mlrval.Mlrval, doLocal, produceNanoseconds bool) *mlrval.Mlrval {
|
|
if !input1.IsString() {
|
|
return mlrval.FromNotStringError("strptime", input1)
|
|
}
|
|
if !input2.IsString() {
|
|
return mlrval.FromNotStringError("strptime", input2)
|
|
}
|
|
timeString := input1.AcquireStringValue()
|
|
formatString := input2.AcquireStringValue()
|
|
|
|
var t time.Time
|
|
var err error
|
|
if doLocal {
|
|
t, err = strptime.ParseLocal(timeString, formatString)
|
|
} else {
|
|
t, err = strptime.Parse(timeString, formatString)
|
|
}
|
|
if err != nil {
|
|
return mlrval.FromError(err)
|
|
}
|
|
|
|
if produceNanoseconds {
|
|
return mlrval.FromInt(t.UnixNano())
|
|
} else {
|
|
return mlrval.FromFloat(float64(t.UnixNano()) / 1.0e9)
|
|
}
|
|
}
|
|
|
|
// ----------------------------------------------------------------
|
|
|
|
func BIF_strptime_local_ternary(input1, input2, input3 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
return bif_strptime_local_ternary_aux(input1, input2, input3, false)
|
|
}
|
|
|
|
func BIF_strpntime_local_ternary(input1, input2, input3 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
return bif_strptime_local_ternary_aux(input1, input2, input3, true)
|
|
}
|
|
|
|
func BIF_localtime2sec_binary(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
return bif_strptime_local_ternary_aux(input1, ptr_ISO8601_LOCAL_TIME_FORMAT, input2, false)
|
|
}
|
|
|
|
func BIF_localtime2nsec_binary(input1, input2 *mlrval.Mlrval) *mlrval.Mlrval {
|
|
return bif_strptime_local_ternary_aux(input1, ptr_ISO8601_LOCAL_TIME_FORMAT, input2, true)
|
|
}
|
|
|
|
func bif_strptime_local_ternary_aux(input1, input2, input3 *mlrval.Mlrval, produceNanoseconds bool) *mlrval.Mlrval {
|
|
if !input1.IsString() {
|
|
return mlrval.FromNotStringError("strptime_local", input1)
|
|
}
|
|
if !input2.IsString() {
|
|
return mlrval.FromNotStringError("strptime_local", input2)
|
|
}
|
|
if !input3.IsString() {
|
|
return mlrval.FromNotStringError("strptime_local", input3)
|
|
}
|
|
|
|
timeString := input1.AcquireStringValue()
|
|
formatString := input2.AcquireStringValue()
|
|
locationString := input3.AcquireStringValue()
|
|
|
|
location, err := time.LoadLocation(locationString)
|
|
if err != nil {
|
|
return mlrval.FromError(err)
|
|
}
|
|
|
|
t, err := strptime.ParseLocation(timeString, formatString, location)
|
|
if err != nil {
|
|
return mlrval.FromError(err)
|
|
}
|
|
|
|
if produceNanoseconds {
|
|
return mlrval.FromInt(t.UnixNano())
|
|
} else {
|
|
return mlrval.FromFloat(float64(t.UnixNano()) / 1.0e9)
|
|
}
|
|
}
|