mirror of
				https://gitea.com/Lydanne/buildx.git
				synced 2025-11-04 10:03:42 +08:00 
			
		
		
		
	
		
			
				
	
	
		
			135 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
			
		
		
	
	
			135 lines
		
	
	
		
			3.3 KiB
		
	
	
	
		
			Go
		
	
	
	
	
	
package time
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"fmt"
 | 
						|
	"math/big"
 | 
						|
	"strings"
 | 
						|
	"time"
 | 
						|
)
 | 
						|
 | 
						|
const (
 | 
						|
	// dateTimeFormat is a IMF-fixdate formatted RFC3339 section 5.6
 | 
						|
	dateTimeFormatInput    = "2006-01-02T15:04:05.999999999Z"
 | 
						|
	dateTimeFormatInputNoZ = "2006-01-02T15:04:05.999999999"
 | 
						|
	dateTimeFormatOutput   = "2006-01-02T15:04:05.999Z"
 | 
						|
 | 
						|
	// httpDateFormat is a date time defined by RFC 7231#section-7.1.1.1
 | 
						|
	// IMF-fixdate with no UTC offset.
 | 
						|
	httpDateFormat = "Mon, 02 Jan 2006 15:04:05 GMT"
 | 
						|
	// Additional formats needed for compatibility.
 | 
						|
	httpDateFormatSingleDigitDay             = "Mon, _2 Jan 2006 15:04:05 GMT"
 | 
						|
	httpDateFormatSingleDigitDayTwoDigitYear = "Mon, _2 Jan 06 15:04:05 GMT"
 | 
						|
)
 | 
						|
 | 
						|
var millisecondFloat = big.NewFloat(1e3)
 | 
						|
 | 
						|
// FormatDateTime formats value as a date-time, (RFC3339 section 5.6)
 | 
						|
//
 | 
						|
// Example: 1985-04-12T23:20:50.52Z
 | 
						|
func FormatDateTime(value time.Time) string {
 | 
						|
	return value.UTC().Format(dateTimeFormatOutput)
 | 
						|
}
 | 
						|
 | 
						|
// ParseDateTime parses a string as a date-time, (RFC3339 section 5.6)
 | 
						|
//
 | 
						|
// Example: 1985-04-12T23:20:50.52Z
 | 
						|
func ParseDateTime(value string) (time.Time, error) {
 | 
						|
	return tryParse(value,
 | 
						|
		dateTimeFormatInput,
 | 
						|
		dateTimeFormatInputNoZ,
 | 
						|
		time.RFC3339Nano,
 | 
						|
		time.RFC3339,
 | 
						|
	)
 | 
						|
}
 | 
						|
 | 
						|
// FormatHTTPDate formats value as a http-date, (RFC 7231#section-7.1.1.1 IMF-fixdate)
 | 
						|
//
 | 
						|
// Example: Tue, 29 Apr 2014 18:30:38 GMT
 | 
						|
func FormatHTTPDate(value time.Time) string {
 | 
						|
	return value.UTC().Format(httpDateFormat)
 | 
						|
}
 | 
						|
 | 
						|
// ParseHTTPDate parses a string as a http-date, (RFC 7231#section-7.1.1.1 IMF-fixdate)
 | 
						|
//
 | 
						|
// Example: Tue, 29 Apr 2014 18:30:38 GMT
 | 
						|
func ParseHTTPDate(value string) (time.Time, error) {
 | 
						|
	return tryParse(value,
 | 
						|
		httpDateFormat,
 | 
						|
		httpDateFormatSingleDigitDay,
 | 
						|
		httpDateFormatSingleDigitDayTwoDigitYear,
 | 
						|
		time.RFC850,
 | 
						|
		time.ANSIC,
 | 
						|
	)
 | 
						|
}
 | 
						|
 | 
						|
// FormatEpochSeconds returns value as a Unix time in seconds with with decimal precision
 | 
						|
//
 | 
						|
// Example: 1515531081.123
 | 
						|
func FormatEpochSeconds(value time.Time) float64 {
 | 
						|
	ms := value.UnixNano() / int64(time.Millisecond)
 | 
						|
	return float64(ms) / 1e3
 | 
						|
}
 | 
						|
 | 
						|
// ParseEpochSeconds returns value as a Unix time in seconds with with decimal precision
 | 
						|
//
 | 
						|
// Example: 1515531081.123
 | 
						|
func ParseEpochSeconds(value float64) time.Time {
 | 
						|
	f := big.NewFloat(value)
 | 
						|
	f = f.Mul(f, millisecondFloat)
 | 
						|
	i, _ := f.Int64()
 | 
						|
	// Offset to `UTC` because time.Unix returns the time value based on system
 | 
						|
	// local setting.
 | 
						|
	return time.Unix(0, i*1e6).UTC()
 | 
						|
}
 | 
						|
 | 
						|
func tryParse(v string, formats ...string) (time.Time, error) {
 | 
						|
	var errs parseErrors
 | 
						|
	for _, f := range formats {
 | 
						|
		t, err := time.Parse(f, v)
 | 
						|
		if err != nil {
 | 
						|
			errs = append(errs, parseError{
 | 
						|
				Format: f,
 | 
						|
				Err:    err,
 | 
						|
			})
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		return t, nil
 | 
						|
	}
 | 
						|
 | 
						|
	return time.Time{}, fmt.Errorf("unable to parse time string, %w", errs)
 | 
						|
}
 | 
						|
 | 
						|
type parseErrors []parseError
 | 
						|
 | 
						|
func (es parseErrors) Error() string {
 | 
						|
	var s strings.Builder
 | 
						|
	for _, e := range es {
 | 
						|
		fmt.Fprintf(&s, "\n * %q: %v", e.Format, e.Err)
 | 
						|
	}
 | 
						|
 | 
						|
	return "parse errors:" + s.String()
 | 
						|
}
 | 
						|
 | 
						|
type parseError struct {
 | 
						|
	Format string
 | 
						|
	Err    error
 | 
						|
}
 | 
						|
 | 
						|
// SleepWithContext will wait for the timer duration to expire, or until the context
 | 
						|
// is canceled. Whichever happens first. If the context is canceled the
 | 
						|
// Context's error will be returned.
 | 
						|
func SleepWithContext(ctx context.Context, dur time.Duration) error {
 | 
						|
	t := time.NewTimer(dur)
 | 
						|
	defer t.Stop()
 | 
						|
 | 
						|
	select {
 | 
						|
	case <-t.C:
 | 
						|
		break
 | 
						|
	case <-ctx.Done():
 | 
						|
		return ctx.Err()
 | 
						|
	}
 | 
						|
 | 
						|
	return nil
 | 
						|
}
 |