You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

113 regels
3.6 KiB

  1. // Copyright 2016 The Go Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package ptypes
  5. import (
  6. "errors"
  7. "fmt"
  8. "time"
  9. timestamppb "github.com/golang/protobuf/ptypes/timestamp"
  10. )
  11. // Range of google.protobuf.Duration as specified in timestamp.proto.
  12. const (
  13. // Seconds field of the earliest valid Timestamp.
  14. // This is time.Date(1, 1, 1, 0, 0, 0, 0, time.UTC).Unix().
  15. minValidSeconds = -62135596800
  16. // Seconds field just after the latest valid Timestamp.
  17. // This is time.Date(10000, 1, 1, 0, 0, 0, 0, time.UTC).Unix().
  18. maxValidSeconds = 253402300800
  19. )
  20. // Timestamp converts a timestamppb.Timestamp to a time.Time.
  21. // It returns an error if the argument is invalid.
  22. //
  23. // Unlike most Go functions, if Timestamp returns an error, the first return
  24. // value is not the zero time.Time. Instead, it is the value obtained from the
  25. // time.Unix function when passed the contents of the Timestamp, in the UTC
  26. // locale. This may or may not be a meaningful time; many invalid Timestamps
  27. // do map to valid time.Times.
  28. //
  29. // A nil Timestamp returns an error. The first return value in that case is
  30. // undefined.
  31. //
  32. // Deprecated: Call the ts.AsTime and ts.CheckValid methods instead.
  33. func Timestamp(ts *timestamppb.Timestamp) (time.Time, error) {
  34. // Don't return the zero value on error, because corresponds to a valid
  35. // timestamp. Instead return whatever time.Unix gives us.
  36. var t time.Time
  37. if ts == nil {
  38. t = time.Unix(0, 0).UTC() // treat nil like the empty Timestamp
  39. } else {
  40. t = time.Unix(ts.Seconds, int64(ts.Nanos)).UTC()
  41. }
  42. return t, validateTimestamp(ts)
  43. }
  44. // TimestampNow returns a google.protobuf.Timestamp for the current time.
  45. //
  46. // Deprecated: Call the timestamppb.Now function instead.
  47. func TimestampNow() *timestamppb.Timestamp {
  48. ts, err := TimestampProto(time.Now())
  49. if err != nil {
  50. panic("ptypes: time.Now() out of Timestamp range")
  51. }
  52. return ts
  53. }
  54. // TimestampProto converts the time.Time to a google.protobuf.Timestamp proto.
  55. // It returns an error if the resulting Timestamp is invalid.
  56. //
  57. // Deprecated: Call the timestamppb.New function instead.
  58. func TimestampProto(t time.Time) (*timestamppb.Timestamp, error) {
  59. ts := &timestamppb.Timestamp{
  60. Seconds: t.Unix(),
  61. Nanos: int32(t.Nanosecond()),
  62. }
  63. if err := validateTimestamp(ts); err != nil {
  64. return nil, err
  65. }
  66. return ts, nil
  67. }
  68. // TimestampString returns the RFC 3339 string for valid Timestamps.
  69. // For invalid Timestamps, it returns an error message in parentheses.
  70. //
  71. // Deprecated: Call the ts.AsTime method instead,
  72. // followed by a call to the Format method on the time.Time value.
  73. func TimestampString(ts *timestamppb.Timestamp) string {
  74. t, err := Timestamp(ts)
  75. if err != nil {
  76. return fmt.Sprintf("(%v)", err)
  77. }
  78. return t.Format(time.RFC3339Nano)
  79. }
  80. // validateTimestamp determines whether a Timestamp is valid.
  81. // A valid timestamp represents a time in the range [0001-01-01, 10000-01-01)
  82. // and has a Nanos field in the range [0, 1e9).
  83. //
  84. // If the Timestamp is valid, validateTimestamp returns nil.
  85. // Otherwise, it returns an error that describes the problem.
  86. //
  87. // Every valid Timestamp can be represented by a time.Time,
  88. // but the converse is not true.
  89. func validateTimestamp(ts *timestamppb.Timestamp) error {
  90. if ts == nil {
  91. return errors.New("timestamp: nil Timestamp")
  92. }
  93. if ts.Seconds < minValidSeconds {
  94. return fmt.Errorf("timestamp: %v before 0001-01-01", ts)
  95. }
  96. if ts.Seconds >= maxValidSeconds {
  97. return fmt.Errorf("timestamp: %v after 10000-01-01", ts)
  98. }
  99. if ts.Nanos < 0 || ts.Nanos >= 1e9 {
  100. return fmt.Errorf("timestamp: %v: nanos not in range [0, 1e9)", ts)
  101. }
  102. return nil
  103. }