1. Decode Twitter Snowflake ID in C#

Extract timestamp, worker ID, process ID, and sequence from a Twitter Snowflake ID.

using System; public class TwitterSnowflakeDecoder { private const long TWITTER_EPOCH = 1288834974657L; public static void Decode(long snowflakeId) { // Extract timestamp (first 41 bits) long timestamp = (snowflakeId >> 22) + TWITTER_EPOCH; // Extract worker ID (next 5 bits) long workerId = (snowflakeId >> 17) & 0x1F; // Extract process ID (next 5 bits) long processId = (snowflakeId >> 12) & 0x1F; // Extract sequence (last 12 bits) long sequence = snowflakeId & 0xFFF; // Convert to DateTime DateTimeOffset date = DateTimeOffset.FromUnixTimeMilliseconds(timestamp); Console.WriteLine($"Snowflake ID: {snowflakeId}"); Console.WriteLine($"Timestamp: {date}"); Console.WriteLine($"Worker ID: {workerId}"); Console.WriteLine($"Process ID: {processId}"); Console.WriteLine($"Sequence: {sequence}"); } static void Main(string[] args) { Decode(1382350606417817604L); } }

2. Generate Twitter Snowflake IDs in C#

Thread-safe Snowflake ID generator implementation.

using System; using System.Threading; public class TwitterSnowflakeGenerator { private const long TWITTER_EPOCH = 1288834974657L; private const long WORKER_ID_BITS = 5L; private const long PROCESS_ID_BITS = 5L; private const long SEQUENCE_BITS = 12L; private const long MAX_WORKER_ID = ~(-1L << (int)WORKER_ID_BITS); private const long MAX_PROCESS_ID = ~(-1L << (int)PROCESS_ID_BITS); private const long MAX_SEQUENCE = ~(-1L << (int)SEQUENCE_BITS); private readonly long _workerId; private readonly long _processId; private long _sequence = 0L; private long _lastTimestamp = -1L; private readonly object _lock = new object(); public TwitterSnowflakeGenerator(long workerId, long processId) { if (workerId > MAX_WORKER_ID || workerId < 0) throw new ArgumentException("Worker ID out of range"); if (processId > MAX_PROCESS_ID || processId < 0) throw new ArgumentException("Process ID out of range"); _workerId = workerId; _processId = processId; } public long NextId() { lock (_lock) { long timestamp = GetCurrentTimestamp(); if (timestamp < _lastTimestamp) throw new InvalidOperationException("Clock moved backwards"); if (timestamp == _lastTimestamp) { _sequence = (_sequence + 1) & MAX_SEQUENCE; if (_sequence == 0) { // Sequence exhausted, wait for next millisecond timestamp = WaitNextMillis(_lastTimestamp); } } else { _sequence = 0L; } _lastTimestamp = timestamp; // Combine all parts into Snowflake ID return ((timestamp - TWITTER_EPOCH) << 22) | (_workerId << 17) | (_processId << 12) | _sequence; } } private long GetCurrentTimestamp() { return DateTimeOffset.UtcNow.ToUnixTimeMilliseconds(); } private long WaitNextMillis(long lastTimestamp) { long timestamp = GetCurrentTimestamp(); while (timestamp <= lastTimestamp) { Thread.Sleep(1); timestamp = GetCurrentTimestamp(); } return timestamp; } static void Main(string[] args) { var generator = new TwitterSnowflakeGenerator(1, 1); // Generate 5 IDs for (int i = 0; i < 5; i++) { Console.WriteLine($"Generated ID: {generator.NextId()}"); } } }

3. Complete Snowflake Utility Class

Production-ready utility class with both generation and decoding.

using System; public class TwitterSnowflake { private const long TWITTER_EPOCH = 1288834974657L; public class SnowflakeInfo { public long Id { get; set; } public long Timestamp { get; set; } public int WorkerId { get; set; } public int ProcessId { get; set; } public int Sequence { get; set; } public DateTimeOffset Date => DateTimeOffset.FromUnixTimeMilliseconds(Timestamp); public string FormattedDate => Date.ToString("yyyy-MM-dd HH:mm:ss"); public override string ToString() { return $"SnowflakeInfo {{ Id={Id}, Date={FormattedDate}, " + $"Worker={WorkerId}, Process={ProcessId}, Seq={Sequence} }}"; } } public static SnowflakeInfo Decode(long snowflakeId) { long timestamp = (snowflakeId >> 22) + TWITTER_EPOCH; int workerId = (int)((snowflakeId >> 17) & 0x1F); int processId = (int)((snowflakeId >> 12) & 0x1F); int sequence = (int)(snowflakeId & 0xFFF); return new SnowflakeInfo { Id = snowflakeId, Timestamp = timestamp, WorkerId = workerId, ProcessId = processId, Sequence = sequence }; } static void Main(string[] args) { // Example: Decode a Twitter ID long tweetId = 1382350606417817604L; var info = Decode(tweetId); Console.WriteLine(info); } }

Last updated

Twitter Snowflake ID C# Implementation

Complete C# implementation for working with Twitter Snowflake IDs. Includes production-ready code for decoding existing IDs and generating new ones with thread-safety using lock statements.

Key Features

Thread-Safe

Lock statements prevent race conditions

Twitter Snowflake ID in C# — Examples

This page provides C# code for decoding Twitter Snowflake IDs and extracting their embedded timestamps. All examples are production-ready and use idiomatic modern C# (.NET 6+).

Basic Decoder

// C# — basic Twitter Snowflake ID decoder
using System;

public static class TwitterSnowflake
{
    // Twitter's custom epoch: November 4, 2010 01:42:54.657 UTC
    private const long TwitterEpochMs = 1288834974657L;
    
    public static DateTimeOffset Decode(long id)
    {
        long timestampMs = (id >> 22) + TwitterEpochMs;
        return DateTimeOffset.FromUnixTimeMilliseconds(timestampMs);
    }
    
    public static int GetDatacenterId(long id) => (int)((id >> 17) & 0x1F);
    public static int GetWorkerId(long id)     => (int)((id >> 12) & 0x1F);
    public static int GetSequence(long id)     => (int)(id & 0xFFF);
}

// Usage
long tweetId = 1529877576591609861L;
DateTimeOffset date = TwitterSnowflake.Decode(tweetId);

Console.WriteLine($"Date (UTC): {date.UtcDateTime:yyyy-MM-dd HH:mm:ss}");
Console.WriteLine($"ISO 8601:   {date:O}");
Console.WriteLine($"Unix (s):   {date.ToUnixTimeSeconds()}");
Console.WriteLine($"Datacenter: {TwitterSnowflake.GetDatacenterId(tweetId)}");
Console.WriteLine($"Worker:     {TwitterSnowflake.GetWorkerId(tweetId)}");
Console.WriteLine($"Sequence:   {TwitterSnowflake.GetSequence(tweetId)}");

Full Decoder Class with Record Return Type

// C# — decoder returning a structured result
using System;

public record SnowflakeComponents(
    long Id,
    DateTimeOffset CreatedAt,
    long TimestampMs,
    int DatacenterId,
    int WorkerId,
    int Sequence
);

public static class TwitterSnowflake
{
    private const long TwitterEpochMs = 1288834974657L;
    
    public static SnowflakeComponents Decode(long id)
    {
        long timestampMs = (id >> 22) + TwitterEpochMs;
        
        return new SnowflakeComponents(
            Id:           id,
            CreatedAt:    DateTimeOffset.FromUnixTimeMilliseconds(timestampMs),
            TimestampMs:  timestampMs,
            DatacenterId: (int)((id >> 17) & 0x1F),
            WorkerId:     (int)((id >> 12) & 0x1F),
            Sequence:     (int)(id & 0xFFF)
        );
    }
    
    // Reverse: convert a DateTimeOffset to the minimum Snowflake ID for that moment
    public static long DateToMinId(DateTimeOffset date)
    {
        long tsMs = date.ToUnixTimeMilliseconds() - TwitterEpochMs;
        if (tsMs < 0)
            throw new ArgumentException("Date is before Twitter's Snowflake epoch");
        return tsMs << 22;
    }
}

// Usage
var components = TwitterSnowflake.Decode(1529877576591609861L);
Console.WriteLine(components);

Extension Methods

// C# — extension methods for clean syntax
using System;

public static class SnowflakeExtensions
{
    private const long TwitterEpochMs = 1288834974657L;
    
    public static DateTimeOffset ToTwitterDate(this long id)
    {
        long timestampMs = (id >> 22) + TwitterEpochMs;
        return DateTimeOffset.FromUnixTimeMilliseconds(timestampMs);
    }
    
    public static bool IsSnowflakeId(this long id)
    {
        // Snowflake IDs are larger than ~27 billion
        return id > 27_000_000_000L;
    }
}

// Usage
long tweetId = 1529877576591609861L;
DateTimeOffset date = tweetId.ToTwitterDate();
Console.WriteLine($"Created: {date:yyyy-MM-dd HH:mm:ss} UTC");
Console.WriteLine($"Is Snowflake: {tweetId.IsSnowflakeId()}");

Batch Processing with LINQ

// C# — batch decode a collection of tweet IDs
using System;
using System.Collections.Generic;
using System.Linq;

var tweetIds = new List<long>
{
    1529877576591609861L,
    1700000000000000000L,
    1800000000000000000L,
    1900000000000000000L,
};

var decoded = tweetIds
    .Select(id => new
    {
        Id = id,
        Date = TwitterSnowflake.Decode(id).CreatedAt,
        Sequence = TwitterSnowflake.GetSequence(id)
    })
    .OrderBy(x => x.Id) // Sort chronologically
    .ToList();

foreach (var item in decoded)
{
    Console.WriteLine($"{item.Id} → {item.Date:yyyy-MM-dd HH:mm:ss} UTC (seq: {item.Sequence})");
}

Filtering Tweets by Date Range

// C# — filter tweets by decoded date range
using System;
using System.Collections.Generic;
using System.Linq;

var tweets = new List<(long Id, string Text)>
{
    (1529877576591609861L, "Tweet from May 2022"),
    (1700000000000000000L, "Tweet from milestone"),
    (1800000000000000000L, "Another milestone tweet"),
};

var start = new DateTimeOffset(2022, 1, 1, 0, 0, 0, TimeSpan.Zero);
var end   = new DateTimeOffset(2023, 1, 1, 0, 0, 0, TimeSpan.Zero);

var filtered = tweets
    .Where(t => {
        var date = TwitterSnowflake.Decode(t.Id).CreatedAt;
        return date >= start && date < end;
    })
    .ToList();

Console.WriteLine($"Tweets in 2022: {filtered.Count}");

Unit Tests (xUnit)

// C# — xUnit tests for the Snowflake decoder
using Xunit;
using System;

public class TwitterSnowflakeTests
{
    [Fact]
    public void Decode_KnownId_ReturnsCorrectYear()
    {
        long id = 1529877576591609861L;
        var result = TwitterSnowflake.Decode(id);
        Assert.Equal(2022, result.CreatedAt.Year);
    }
    
    [Fact]
    public void Decode_ExtractsCorrectComponents()
    {
        long id = 1529877576591609861L;
        var result = TwitterSnowflake.Decode(id);
        
        Assert.True(result.DatacenterId >= 0 && result.DatacenterId <= 31);
        Assert.True(result.WorkerId >= 0 && result.WorkerId <= 31);
        Assert.True(result.Sequence >= 0 && result.Sequence <= 4095);
    }
    
    [Fact]
    public void DateToMinId_RoundTrip_IsConsistent()
    {
        var date = new DateTimeOffset(2023, 1, 1, 0, 0, 0, TimeSpan.Zero);
        long minId = TwitterSnowflake.DateToMinId(date);
        var decoded = TwitterSnowflake.Decode(minId);
        
        // Decoded date should be within 1ms of the input date
        Assert.True(Math.Abs((decoded.CreatedAt - date).TotalMilliseconds) < 1);
    }
}

Parallel Processing for Large Datasets

// C# — parallel batch decode for high throughput
using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;

public static Dictionary<long, DateTimeOffset> BatchDecodeParallel(IEnumerable<long> ids)
{
    var results = new ConcurrentDictionary<long, DateTimeOffset>();
    
    Parallel.ForEach(ids, id =>
    {
        var date = TwitterSnowflake.Decode(id).CreatedAt;
        results[id] = date;
    });
    
    return new Dictionary<long, DateTimeOffset>(results);
}

// Usage
var ids = Enumerable.Range(0, 10000)
    .Select(i => 1529877576591609861L + i)
    .ToList();

var decoded = BatchDecodeParallel(ids);
Console.WriteLine($"Decoded {decoded.Count} IDs");

These C# examples cover all common use cases for working with Twitter Snowflake IDs in .NET applications. The decoder is fast, accurate, and handles all valid Snowflake IDs correctly.

Production Ready

Error handling and validation included

High Performance

Efficient bit operations for speed

Modern C#

Uses latest C# features and patterns

NuGet Packages

<!-- No external packages required --> <!-- Uses only .NET standard library -->

Best Practices

  • Use long data type for Snowflake IDs (not int)
  • Always use lock statements for ID generation
  • Handle clock backwards scenarios with exceptions
  • Use unique worker and process IDs in distributed systems
  • Consider using dependency injection for generator instances
  • Add logging with ILogger for production environments

Common Use Cases

  • Decoding Twitter API responses in .NET applications
  • Building Twitter integration services with ASP.NET
  • Implementing custom Snowflake ID systems
  • Analyzing Twitter data in C# applications
  • Creating distributed ID generators for microservices

Frequently Asked Questions

Use bit shifting to extract components: timestamp = (id >> 22) + TWITTER_EPOCH, workerId = (id >> 17) & 0x1F, processId = (id >> 12) & 0x1F, sequence = id & 0xFFF. Twitter's epoch is 1288834974657L milliseconds. Convert to DateTime using DateTimeOffset.FromUnixTimeMilliseconds(timestamp).

Use C#'s long data type for Twitter Snowflake IDs. Snowflake IDs are 64-bit integers that fit perfectly in C#'s long (System.Int64). Avoid using int (32-bit) as it's too small for Snowflake IDs.

Generate Snowflake IDs by combining: timestamp minus TWITTER_EPOCH shifted left 22 bits, workerId shifted left 17 bits, processId shifted left 12 bits, then OR with sequence. Use lock statements for thread-safety and increment sequence for IDs generated in the same millisecond.

You must implement thread-safety manually using lock statements or System.Threading.Interlocked. Track the last timestamp and sequence number to ensure uniqueness across threads in multi-threaded applications.