diff --git a/ulid.go b/ulid.go index 2064dd4..62c9bd4 100644 --- a/ulid.go +++ b/ulid.go @@ -75,6 +75,9 @@ var ( // ErrScanValue is returned when the value passed to scan cannot be unmarshaled // into the ULID. ErrScanValue = errors.New("ulid: source value must be a string or byte slice") + + // Nil is an empty ULID, all zeros, useful when comparing nil ULIDs + Nil ULID ) // MonotonicReader is an interface that should yield monotonically increasing @@ -416,6 +419,11 @@ func (id ULID) Timestamp() time.Time { return Time(id.Time()) } +// IsZero returns whether the ULID is a zero-value, ie ulid.Nil. +func (id ULID) IsZero() bool { + return bytes.Equal(id[:], Nil[:]) +} + // maxTime is the maximum Unix time in milliseconds that can be // represented in a ULID. var maxTime = ULID{0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF}.Time() diff --git a/ulid_test.go b/ulid_test.go index 43f81c6..510d111 100644 --- a/ulid_test.go +++ b/ulid_test.go @@ -454,6 +454,20 @@ func TestULIDTimestamp(t *testing.T) { } } +func TestZero(t *testing.T) { + t.Parallel() + + var id ulid.ULID + if ok := id.IsZero(); !ok { + t.Error(".IsZero: must return true for empty ULIDs, have false") + } + + id = ulid.MustNew(ulid.Now(), ulid.DefaultEntropy()) + if ok := id.IsZero(); ok { + t.Error(".IsZero: must return false for non-nil ULIDs, have true") + } +} + func TestEntropy(t *testing.T) { t.Parallel()