@@ -797,6 +797,218 @@ func (t *testUnmarshalMapKeyComplex) UnmarshalDynamoDBAttributeValue(av types.At
797797 return nil
798798}
799799
800+ func TestUnmarshalTime_S_SS (t * testing.T ) {
801+ type A struct {
802+ TimeField time.Time
803+ TimeFields []time.Time
804+ TimeFieldsL []time.Time
805+ }
806+ cases := map [string ]struct {
807+ input string
808+ expect time.Time
809+ decodeTimeS func (string ) (time.Time , error )
810+ }{
811+ "String RFC3339Nano (Default)" : {
812+ input : "1970-01-01T00:02:03.01Z" ,
813+ expect : time .Unix (123 , 10000000 ).UTC (),
814+ },
815+ "String UnixDate" : {
816+ input : "Thu Jan 1 00:02:03 UTC 1970" ,
817+ expect : time .Unix (123 , 0 ).UTC (),
818+ decodeTimeS : func (v string ) (time.Time , error ) {
819+ t , err := time .Parse (time .UnixDate , v )
820+ if err != nil {
821+ return time.Time {}, & UnmarshalError {Err : err , Value : v , Type : timeType }
822+ }
823+ return t , nil
824+ },
825+ },
826+ "String RFC3339 millis keeping zeroes" : {
827+ input : "1970-01-01T00:02:03.010Z" ,
828+ expect : time .Unix (123 , 10000000 ).UTC (),
829+ decodeTimeS : func (v string ) (time.Time , error ) {
830+ t , err := time .Parse ("2006-01-02T15:04:05.000Z07:00" , v )
831+ if err != nil {
832+ return time.Time {}, & UnmarshalError {Err : err , Value : v , Type : timeType }
833+ }
834+ return t , nil
835+ },
836+ },
837+ "String RFC822" : {
838+ input : "01 Jan 70 00:02 UTC" ,
839+ expect : time .Unix (120 , 0 ).UTC (),
840+ decodeTimeS : func (v string ) (time.Time , error ) {
841+ t , err := time .Parse (time .RFC822 , v )
842+ if err != nil {
843+ return time.Time {}, & UnmarshalError {Err : err , Value : v , Type : timeType }
844+ }
845+ return t , nil
846+ },
847+ },
848+ }
849+ for name , c := range cases {
850+ t .Run (name , func (t * testing.T ) {
851+ inputMap := & types.AttributeValueMemberM {
852+ Value : map [string ]types.AttributeValue {
853+ "TimeField" : & types.AttributeValueMemberS {Value : c .input },
854+ "TimeFields" : & types.AttributeValueMemberSS {Value : []string {c .input }},
855+ "TimeFieldsL" : & types.AttributeValueMemberL {Value : []types.AttributeValue {
856+ & types.AttributeValueMemberS {Value : c .input },
857+ }},
858+ },
859+ }
860+ expectedValue := A {
861+ TimeField : c .expect ,
862+ TimeFields : []time.Time {c .expect },
863+ TimeFieldsL : []time.Time {c .expect },
864+ }
865+
866+ var actualValue A
867+ if err := UnmarshalWithOptions (inputMap , & actualValue , func (options * DecoderOptions ) {
868+ if c .decodeTimeS != nil {
869+ options .DecodeTime .S = c .decodeTimeS
870+ }
871+ }); err != nil {
872+ t .Errorf ("expect no error, got %v" , err )
873+ }
874+ if diff := cmp .Diff (expectedValue , actualValue , getIgnoreAVUnexportedOptions ()... ); diff != "" {
875+ t .Errorf ("expect attribute value match\n %s" , diff )
876+ }
877+ })
878+ }
879+ }
880+
881+ func TestUnmarshalTime_N_NS (t * testing.T ) {
882+ type A struct {
883+ TimeField time.Time
884+ TimeFields []time.Time
885+ TimeFieldsL []time.Time
886+ }
887+ cases := map [string ]struct {
888+ input string
889+ expect time.Time
890+ decodeTimeN func (string ) (time.Time , error )
891+ }{
892+ "Number Unix seconds (Default)" : {
893+ input : "123" ,
894+ expect : time .Unix (123 , 0 ),
895+ },
896+ "Number Unix milli" : {
897+ input : "123010" ,
898+ expect : time .Unix (123 , 10000000 ),
899+ decodeTimeN : func (v string ) (time.Time , error ) {
900+ n , err := strconv .ParseInt (v , 10 , 64 )
901+ if err != nil {
902+ return time.Time {}, & UnmarshalError {
903+ Err : err , Value : v , Type : timeType ,
904+ }
905+ }
906+ return time .Unix (0 , n * int64 (time .Millisecond )), nil
907+ },
908+ },
909+ }
910+ for name , c := range cases {
911+ t .Run (name , func (t * testing.T ) {
912+ inputMap := & types.AttributeValueMemberM {
913+ Value : map [string ]types.AttributeValue {
914+ "TimeField" : & types.AttributeValueMemberN {Value : c .input },
915+ "TimeFields" : & types.AttributeValueMemberNS {Value : []string {c .input }},
916+ "TimeFieldsL" : & types.AttributeValueMemberL {Value : []types.AttributeValue {
917+ & types.AttributeValueMemberN {Value : c .input },
918+ }},
919+ },
920+ }
921+ expectedValue := A {
922+ TimeField : c .expect ,
923+ TimeFields : []time.Time {c .expect },
924+ TimeFieldsL : []time.Time {c .expect },
925+ }
926+
927+ var actualValue A
928+ if err := UnmarshalWithOptions (inputMap , & actualValue , func (options * DecoderOptions ) {
929+ if c .decodeTimeN != nil {
930+ options .DecodeTime .N = c .decodeTimeN
931+ }
932+ }); err != nil {
933+ t .Errorf ("expect no error, got %v" , err )
934+ }
935+ if diff := cmp .Diff (expectedValue , actualValue , getIgnoreAVUnexportedOptions ()... ); diff != "" {
936+ t .Errorf ("expect attribute value match\n %s" , diff )
937+ }
938+ })
939+ }
940+ }
941+
942+ func TestCustomDecodeSAndDefaultDecodeN (t * testing.T ) {
943+ type A struct {
944+ TimeFieldS time.Time
945+ TimeFieldN time.Time
946+ }
947+ inputMap := & types.AttributeValueMemberM {
948+ Value : map [string ]types.AttributeValue {
949+ "TimeFieldS" : & types.AttributeValueMemberS {Value : "01 Jan 70 00:02 UTC" },
950+ "TimeFieldN" : & types.AttributeValueMemberN {Value : "123" },
951+ },
952+ }
953+ expectedValue := A {
954+ TimeFieldS : time .Unix (120 , 0 ).UTC (),
955+ TimeFieldN : time .Unix (123 , 0 ).UTC (),
956+ }
957+
958+ var actualValue A
959+ if err := UnmarshalWithOptions (inputMap , & actualValue , func (options * DecoderOptions ) {
960+ // overriding only the S time decoder will keep the default N time decoder
961+ options .DecodeTime .S = func (v string ) (time.Time , error ) {
962+ t , err := time .Parse (time .RFC822 , v )
963+ if err != nil {
964+ return time.Time {}, & UnmarshalError {Err : err , Value : v , Type : timeType }
965+ }
966+ return t , nil
967+ }
968+ }); err != nil {
969+ t .Errorf ("expect no error, got %v" , err )
970+ }
971+ if diff := cmp .Diff (expectedValue , actualValue , getIgnoreAVUnexportedOptions ()... ); diff != "" {
972+ t .Errorf ("expect attribute value match\n %s" , diff )
973+ }
974+ }
975+
976+ func TestCustomDecodeNAndDefaultDecodeS (t * testing.T ) {
977+ type A struct {
978+ TimeFieldS time.Time
979+ TimeFieldN time.Time
980+ }
981+ inputMap := & types.AttributeValueMemberM {
982+ Value : map [string ]types.AttributeValue {
983+ "TimeFieldS" : & types.AttributeValueMemberS {Value : "1970-01-01T00:02:03.01Z" },
984+ "TimeFieldN" : & types.AttributeValueMemberN {Value : "123010" },
985+ },
986+ }
987+ expectedValue := A {
988+ TimeFieldS : time .Unix (123 , 10000000 ).UTC (),
989+ TimeFieldN : time .Unix (123 , 10000000 ).UTC (),
990+ }
991+
992+ var actualValue A
993+ if err := UnmarshalWithOptions (inputMap , & actualValue , func (options * DecoderOptions ) {
994+ // overriding only the N time decoder will keep the default S time decoder
995+ options .DecodeTime .N = func (v string ) (time.Time , error ) {
996+ n , err := strconv .ParseInt (v , 10 , 64 )
997+ if err != nil {
998+ return time.Time {}, & UnmarshalError {
999+ Err : err , Value : v , Type : timeType ,
1000+ }
1001+ }
1002+ return time .Unix (0 , n * int64 (time .Millisecond )), nil
1003+ }
1004+ }); err != nil {
1005+ t .Errorf ("expect no error, got %v" , err )
1006+ }
1007+ if diff := cmp .Diff (expectedValue , actualValue , getIgnoreAVUnexportedOptions ()... ); diff != "" {
1008+ t .Errorf ("expect attribute value match\n %s" , diff )
1009+ }
1010+ }
1011+
8001012func TestUnmarshalMap_keyTypes (t * testing.T ) {
8011013 type StrAlias string
8021014 type IntAlias int
0 commit comments