github.com/mdaxf/iac@v0.0.0-20240519030858-58a061660378/vendor_skip/go.mongodb.org/mongo-driver/bson/bsoncodec/time_codec.go (about)

     1  // Copyright (C) MongoDB, Inc. 2017-present.
     2  //
     3  // Licensed under the Apache License, Version 2.0 (the "License"); you may
     4  // not use this file except in compliance with the License. You may obtain
     5  // a copy of the License at http://www.apache.org/licenses/LICENSE-2.0
     6  
     7  package bsoncodec
     8  
     9  import (
    10  	"fmt"
    11  	"reflect"
    12  	"time"
    13  
    14  	"go.mongodb.org/mongo-driver/bson/bsonoptions"
    15  	"go.mongodb.org/mongo-driver/bson/bsonrw"
    16  	"go.mongodb.org/mongo-driver/bson/bsontype"
    17  	"go.mongodb.org/mongo-driver/bson/primitive"
    18  )
    19  
    20  const (
    21  	timeFormatString = "2006-01-02T15:04:05.999Z07:00"
    22  )
    23  
    24  // TimeCodec is the Codec used for time.Time values.
    25  //
    26  // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
    27  // TimeCodec registered.
    28  type TimeCodec struct {
    29  	// UseLocalTimeZone specifies if we should decode into the local time zone. Defaults to false.
    30  	//
    31  	// Deprecated: Use bson.Decoder.UseLocalTimeZone instead.
    32  	UseLocalTimeZone bool
    33  }
    34  
    35  var (
    36  	defaultTimeCodec = NewTimeCodec()
    37  
    38  	// Assert that defaultTimeCodec satisfies the typeDecoder interface, which allows it to be used
    39  	// by collection type decoders (e.g. map, slice, etc) to set individual values in a collection.
    40  	_ typeDecoder = defaultTimeCodec
    41  )
    42  
    43  // NewTimeCodec returns a TimeCodec with options opts.
    44  //
    45  // Deprecated: Use [go.mongodb.org/mongo-driver/bson.NewRegistry] to get a registry with the
    46  // TimeCodec registered.
    47  func NewTimeCodec(opts ...*bsonoptions.TimeCodecOptions) *TimeCodec {
    48  	timeOpt := bsonoptions.MergeTimeCodecOptions(opts...)
    49  
    50  	codec := TimeCodec{}
    51  	if timeOpt.UseLocalTimeZone != nil {
    52  		codec.UseLocalTimeZone = *timeOpt.UseLocalTimeZone
    53  	}
    54  	return &codec
    55  }
    56  
    57  func (tc *TimeCodec) decodeType(dc DecodeContext, vr bsonrw.ValueReader, t reflect.Type) (reflect.Value, error) {
    58  	if t != tTime {
    59  		return emptyValue, ValueDecoderError{
    60  			Name:     "TimeDecodeValue",
    61  			Types:    []reflect.Type{tTime},
    62  			Received: reflect.Zero(t),
    63  		}
    64  	}
    65  
    66  	var timeVal time.Time
    67  	switch vrType := vr.Type(); vrType {
    68  	case bsontype.DateTime:
    69  		dt, err := vr.ReadDateTime()
    70  		if err != nil {
    71  			return emptyValue, err
    72  		}
    73  		timeVal = time.Unix(dt/1000, dt%1000*1000000)
    74  	case bsontype.String:
    75  		// assume strings are in the isoTimeFormat
    76  		timeStr, err := vr.ReadString()
    77  		if err != nil {
    78  			return emptyValue, err
    79  		}
    80  		timeVal, err = time.Parse(timeFormatString, timeStr)
    81  		if err != nil {
    82  			return emptyValue, err
    83  		}
    84  	case bsontype.Int64:
    85  		i64, err := vr.ReadInt64()
    86  		if err != nil {
    87  			return emptyValue, err
    88  		}
    89  		timeVal = time.Unix(i64/1000, i64%1000*1000000)
    90  	case bsontype.Timestamp:
    91  		t, _, err := vr.ReadTimestamp()
    92  		if err != nil {
    93  			return emptyValue, err
    94  		}
    95  		timeVal = time.Unix(int64(t), 0)
    96  	case bsontype.Null:
    97  		if err := vr.ReadNull(); err != nil {
    98  			return emptyValue, err
    99  		}
   100  	case bsontype.Undefined:
   101  		if err := vr.ReadUndefined(); err != nil {
   102  			return emptyValue, err
   103  		}
   104  	default:
   105  		return emptyValue, fmt.Errorf("cannot decode %v into a time.Time", vrType)
   106  	}
   107  
   108  	if !tc.UseLocalTimeZone && !dc.useLocalTimeZone {
   109  		timeVal = timeVal.UTC()
   110  	}
   111  	return reflect.ValueOf(timeVal), nil
   112  }
   113  
   114  // DecodeValue is the ValueDecoderFunc for time.Time.
   115  func (tc *TimeCodec) DecodeValue(dc DecodeContext, vr bsonrw.ValueReader, val reflect.Value) error {
   116  	if !val.CanSet() || val.Type() != tTime {
   117  		return ValueDecoderError{Name: "TimeDecodeValue", Types: []reflect.Type{tTime}, Received: val}
   118  	}
   119  
   120  	elem, err := tc.decodeType(dc, vr, tTime)
   121  	if err != nil {
   122  		return err
   123  	}
   124  
   125  	val.Set(elem)
   126  	return nil
   127  }
   128  
   129  // EncodeValue is the ValueEncoderFunc for time.TIme.
   130  func (tc *TimeCodec) EncodeValue(_ EncodeContext, vw bsonrw.ValueWriter, val reflect.Value) error {
   131  	if !val.IsValid() || val.Type() != tTime {
   132  		return ValueEncoderError{Name: "TimeEncodeValue", Types: []reflect.Type{tTime}, Received: val}
   133  	}
   134  	tt := val.Interface().(time.Time)
   135  	dt := primitive.NewDateTimeFromTime(tt)
   136  	return vw.WriteDateTime(int64(dt))
   137  }