github.com/ndau/noms@v1.0.5/go/util/datetime/date_time.go (about)

     1  // Copyright 2017 Attic Labs, Inc. All rights reserved.
     2  // Licensed under the Apache License, version 2.0:
     3  // http://www.apache.org/licenses/LICENSE-2.0
     4  
     5  // Package datetime implements marshalling of Go DateTime values into Noms structs
     6  // with type DateTimeType.
     7  package datetime
     8  
     9  import (
    10  	"math"
    11  	"time"
    12  
    13  	"github.com/ndau/noms/go/marshal"
    14  	"github.com/ndau/noms/go/types"
    15  )
    16  
    17  const (
    18  	datetypename    = "DateTime"
    19  	hrsEncodingName = "noms-datetime"
    20  )
    21  
    22  // DateTime implements marshaling of time.Time to and from Noms.
    23  type DateTime struct {
    24  	time.Time
    25  }
    26  
    27  // DateTimeType is the Noms type used to represent date time objects in Noms.
    28  // The field secSinceEpoch may contain fractions in cases where seconds are
    29  // not sufficient.
    30  var DateTimeType = types.MakeStructTypeFromFields(datetypename, types.FieldMap{
    31  	"secSinceEpoch": types.NumberType,
    32  })
    33  
    34  var dateTimeTemplate = types.MakeStructTemplate(datetypename, []string{"secSinceEpoch"})
    35  
    36  // Epoch is the unix Epoch. This time is very consistent,
    37  // which makes it useful for testing or checking for uninitialized values
    38  var Epoch = DateTime{time.Unix(0, 0)}
    39  
    40  func init() {
    41  	RegisterHRSCommenter(time.Local)
    42  }
    43  
    44  // Now is an alias for a DateTime initialized with time.Now()
    45  func Now() DateTime {
    46  	return DateTime{time.Now()}
    47  }
    48  
    49  // MarshalNoms makes DateTime implement marshal.Marshaler and it makes
    50  // DateTime marshal into a Noms struct with type DateTimeType.
    51  func (dt DateTime) MarshalNoms(vrw types.ValueReadWriter) (types.Value, error) {
    52  	return dateTimeTemplate.NewStruct([]types.Value{types.Number(float64(dt.Unix()) + float64(dt.Nanosecond())*1e-9)}), nil
    53  }
    54  
    55  // MarshalNomsType makes DateTime implement marshal.TypeMarshaler and it
    56  // allows marshal.MarshalType to work with DateTime.
    57  func (dt DateTime) MarshalNomsType() (*types.Type, error) {
    58  	return DateTimeType, nil
    59  }
    60  
    61  // UnmarshalNoms makes DateTime implement marshal.Unmarshaler and it allows
    62  // Noms struct with type DateTimeType able to be unmarshaled onto a DateTime
    63  // Go struct
    64  func (dt *DateTime) UnmarshalNoms(v types.Value) error {
    65  	strct := struct {
    66  		SecSinceEpoch float64
    67  	}{}
    68  	err := marshal.Unmarshal(v, &strct)
    69  	if err != nil {
    70  		return err
    71  	}
    72  
    73  	s, frac := math.Modf(strct.SecSinceEpoch)
    74  	*dt = DateTime{time.Unix(int64(s), int64(frac*1e9))}
    75  	return nil
    76  }
    77  
    78  type DateTimeCommenter struct {
    79  	tz *time.Location
    80  }
    81  
    82  func (c DateTimeCommenter) Comment(v types.Value) string {
    83  	if !types.IsValueSubtypeOf(v, DateTimeType) {
    84  		return ""
    85  	}
    86  	var dt DateTime
    87  	marshal.MustUnmarshal(v, &dt)
    88  	return dt.In(c.tz).Format(time.RFC3339)
    89  }
    90  
    91  func RegisterHRSCommenter(tz *time.Location) {
    92  	hrsCommenter := DateTimeCommenter{tz: tz}
    93  	types.RegisterHRSCommenter(datetypename, hrsEncodingName, hrsCommenter)
    94  }