github.com/andersfylling/snowflake/v5@v5.0.1/snowflake.go (about)

     1  package snowflake
     2  
     3  import (
     4  	"errors"
     5  	"strconv"
     6  	"time"
     7  )
     8  
     9  const (
    10  	EpochDiscord uint64 = 1420070400000
    11  )
    12  
    13  // NewID creates a new Snowflake Snowflake from a uint64.
    14  func NewSnowflake(id uint64) Snowflake {
    15  	return Snowflake(id)
    16  }
    17  
    18  // Snowflake twitter snowflake design
    19  type Snowflake uint64
    20  
    21  type ID = Snowflake
    22  
    23  // IsZero since snowflake exists of several parts, including a timestamp,
    24  //       I assume a valid snowflake Snowflake is never 0.
    25  func (s Snowflake) IsZero() bool {
    26  	return uint64(s) == 0
    27  }
    28  
    29  // Valid makes sure the snowflake is after the fixed epoch
    30  func (s Snowflake) Valid() bool {
    31  	return (s >> 22) >= 1 // older than 1 millisecond
    32  }
    33  
    34  // String returns the decimal representation of the snowflake Snowflake.
    35  func (s Snowflake) String() string {
    36  	return strconv.FormatUint(uint64(s), 10)
    37  }
    38  
    39  // HexString converts the Snowflake into a hexadecimal string
    40  func (s Snowflake) HexString() string {
    41  	return strconv.FormatUint(uint64(s), 16)
    42  }
    43  
    44  // HexPrettyString converts the Snowflake into a hexadecimal string with the hex prefix 0x
    45  func (s Snowflake) HexPrettyString() string {
    46  	return "0x" + strconv.FormatUint(uint64(s), 16)
    47  }
    48  
    49  // MarshalBinary create a binary literal representation as a string
    50  func (s Snowflake) MarshalBinary() (data []byte, err error) {
    51  	return []byte(strconv.FormatUint(uint64(s), 2)), nil
    52  }
    53  
    54  func (s *Snowflake) UnmarshalBinary(text []byte) (err error) {
    55  	id, err := strconv.ParseUint(string(text), 2, 64)
    56  	if err != nil {
    57  		return
    58  	}
    59  	*s = Snowflake(id)
    60  
    61  	return
    62  }
    63  
    64  func (s *Snowflake) UnmarshalJSON(data []byte) (err error) {
    65  	*s = 0
    66  	length := len(data)
    67  	if length == 0 {
    68  		// Blank value.
    69  		return
    70  	}
    71  	if length == 4 && string(data) == "null" {
    72  		// This is a zero value.
    73  		return
    74  	}
    75  
    76  	// if the snowflake is passed as a string, we account for the double quote wrap
    77  	start := 0
    78  	if data[0] == '"' {
    79  		start++
    80  		length--
    81  	}
    82  	if signed := data[start] == '-'; signed {
    83  		start++
    84  		*s |= 1 << 63
    85  	}
    86  
    87  	var c byte
    88  	var tmp uint64
    89  	for i := start; i < length; i++ {
    90  		c = data[i] - '0'
    91  		if c < 0 || c > 9 {
    92  			err = errors.New("cannot parse non-integer symbol:" + string(data[i]))
    93  			return
    94  		}
    95  		tmp = tmp*10 + uint64(c)
    96  	}
    97  
    98  	*s |= Snowflake(tmp)
    99  	return
   100  }
   101  
   102  func (s Snowflake) MarshalJSON() (data []byte, err error) {
   103  	if s == 0 {
   104  		data = []byte(`null`)
   105  	} else {
   106  		data = []byte(`"` + s.String() + `"`)
   107  	}
   108  	return
   109  }
   110  
   111  func (s Snowflake) MarshalText() (text []byte, err error) {
   112  	text = []byte(s.String())
   113  	err = nil
   114  
   115  	return
   116  }
   117  
   118  func (s *Snowflake) UnmarshalText(text []byte) (err error) {
   119  	id, err := strconv.ParseUint(string(text), 10, 64)
   120  	if err != nil {
   121  		return
   122  	}
   123  	*s = Snowflake(id)
   124  
   125  	return
   126  }
   127  
   128  func (s Snowflake) Date() time.Time {
   129  	epoch := (uint64(s) >> uint64(22)) + EpochDiscord
   130  	return time.Unix(int64(epoch)/1000, 0)
   131  }