├── .gitignore ├── README.md ├── __init__.py └── snowflake.py /.gitignore: -------------------------------------------------------------------------------- 1 | *~ 2 | *.pyc -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | snowflake.py 2 | ============ 3 | 4 | Utility functions for creating and melting [Twitter snowflake][1] ID's. 5 | 6 | [1]: https://github.com/twitter/snowflake 7 | 8 | Examples 9 | -------- 10 | ```python 11 | import time 12 | from snowflake import * 13 | 14 | # using tweet id from https://twitter.com/falcondai/status/345063379196600321 15 | snowflake_id = 345063379196600321 16 | timestamp, data_center, worker, sequence = melt(snowflake_id) 17 | print 'the tweet was created at %s' % local_datetime(timestamp) 18 | 19 | # create a snowflake id for the current millisecond 20 | print make_snowflake(time.time()*1000, 1, 0, 0) 21 | ``` 22 | 23 | License 24 | ------- 25 | MIT License 26 | 27 | Author 28 | ------ 29 | Falcon Dai 30 | -------------------------------------------------------------------------------- /__init__.py: -------------------------------------------------------------------------------- 1 | import snowflake 2 | from snowflake import * 3 | 4 | 5 | -------------------------------------------------------------------------------- /snowflake.py: -------------------------------------------------------------------------------- 1 | import datetime 2 | 3 | # twitter's snowflake parameters 4 | twepoch = 1288834974657L 5 | datacenter_id_bits = 5L 6 | worker_id_bits = 5L 7 | sequence_id_bits = 12L 8 | max_datacenter_id = 1 << datacenter_id_bits 9 | max_worker_id = 1 << worker_id_bits 10 | max_sequence_id = 1 << sequence_id_bits 11 | max_timestamp = 1 << (64L - datacenter_id_bits - worker_id_bits - sequence_id_bits) 12 | 13 | def make_snowflake(timestamp_ms, datacenter_id, worker_id, sequence_id, twepoch=twepoch): 14 | """generate a twitter-snowflake id, based on 15 | https://github.com/twitter/snowflake/blob/master/src/main/scala/com/twitter/service/snowflake/IdWorker.scala 16 | :param: timestamp_ms time since UNIX epoch in milliseconds""" 17 | 18 | sid = ((int(timestamp_ms) - twepoch) % max_timestamp) << datacenter_id_bits << worker_id_bits << sequence_id_bits 19 | sid += (datacenter_id % max_datacenter_id) << worker_id_bits << sequence_id_bits 20 | sid += (worker_id % max_worker_id) << sequence_id_bits 21 | sid += sequence_id % max_sequence_id 22 | 23 | return sid 24 | 25 | def melt(snowflake_id, twepoch=twepoch): 26 | """inversely transform a snowflake id back to its parts.""" 27 | sequence_id = snowflake_id & (max_sequence_id - 1) 28 | worker_id = (snowflake_id >> sequence_id_bits) & (max_worker_id - 1) 29 | datacenter_id = (snowflake_id >> sequence_id_bits >> worker_id_bits) & (max_datacenter_id - 1) 30 | timestamp_ms = snowflake_id >> sequence_id_bits >> worker_id_bits >> datacenter_id_bits 31 | timestamp_ms += twepoch 32 | 33 | return (timestamp_ms, int(datacenter_id), int(worker_id), int(sequence_id)) 34 | 35 | def local_datetime(timestamp_ms): 36 | """convert millisecond timestamp to local datetime object.""" 37 | return datetime.datetime.fromtimestamp(timestamp_ms / 1000.) 38 | 39 | if __name__ == '__main__': 40 | import time 41 | t0 = int(time.time() * 1000) 42 | print local_datetime(t0) 43 | assert(melt(make_snowflake(t0, 0, 0, 0))[0] == t0) 44 | --------------------------------------------------------------------------------