Skip to content

Commit 57281b6

Browse files
committed
Merge branch 'up/feat/snowflake' into chore/all-my-stuffs
2 parents b6a770a + 3a51a6c commit 57281b6

File tree

5 files changed

+100
-0
lines changed

5 files changed

+100
-0
lines changed

src/tools/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ import { tool as energyConverter } from './energy-converter';
2323
import { tool as areaConverter } from './area-converter';
2424
import { tool as angleConverter } from './angle-converter';
2525
import { tool as floatingPointNumberConverter } from './floating-point-number-converter';
26+
import { tool as snowflakeIdExtractor } from './snowflake-id-extractor';
2627
import { tool as emailNormalizer } from './email-normalizer';
2728
import { tool as bounceParser } from './bounce-parser';
2829
import { tool as codeHighlighter } from './code-highlighter';
@@ -361,6 +362,7 @@ export const toolsByCategory: ToolCategory[] = [
361362
jsonDiff,
362363
softwareLicenceCompatibility,
363364
safelinkDecoder,
365+
snowflakeIdExtractor,
364366
apiTester,
365367
bounceParser,
366368
colorWheel,
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Id } from '@vicons/tabler';
2+
import { defineTool } from '../tool';
3+
4+
export const tool = defineTool({
5+
name: 'Snowflake ID extractor',
6+
path: '/snowflake-id-extractor',
7+
description: 'Extract timestamp, machine ID, and sequence number from a Snowflake ID',
8+
keywords: ['snowflake', 'id', 'extractor'],
9+
component: () => import('./snowflake-id-extractor.vue'),
10+
icon: Id,
11+
createdAt: new Date('2024-07-22'),
12+
});
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
import { describe, expect, it } from 'vitest';
2+
import { extractId, extractMachineId, extractTimestamp } from './snowflake-id-extractor.service';
3+
4+
describe('snowflake-id-extractor', () => {
5+
it('extract id from Snowflake ID', () => {
6+
expect(extractId(1263785187301658678n)).toBe(54);
7+
});
8+
it('extract machine id from Snowflake ID', () => {
9+
expect(extractMachineId(1263785187301658678n)).toBe(65);
10+
});
11+
it('extract timestamp from Snowflake ID', () => {
12+
expect(extractTimestamp(1263785187301658678n, new Date(1420070400000))).toStrictEqual(new Date(1721380268646));
13+
});
14+
});
Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
export function extractId(id: bigint) {
2+
return Number(id & 4095n);
3+
}
4+
5+
export function extractMachineId(id: bigint) {
6+
return Number((id >> 12n) & 127n);
7+
}
8+
9+
export function extractTimestamp(id: bigint, epoch: bigint | Date) {
10+
return new Date(Number((id >> 22n) + getTimestamp(epoch)));
11+
}
12+
13+
function getTimestamp(time: bigint | Date) {
14+
return typeof time === 'bigint' ? time : BigInt(new Date(time).getTime());
15+
}
Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,57 @@
1+
<script setup lang="ts">
2+
import { extractId, extractMachineId, extractTimestamp } from './snowflake-id-extractor.service';
3+
4+
const inputId = ref('1263785187301658678');
5+
const inputEpoch = ref('');
6+
7+
const inputProps = {
8+
'labelPosition': 'left',
9+
'labelWidth': '170px',
10+
'labelAlign': 'right',
11+
'readonly': true,
12+
'mb-2': '',
13+
} as const;
14+
</script>
15+
16+
<template>
17+
<div>
18+
<c-card>
19+
<c-input-text v-model:value="inputId" label="Snowflake ID" placeholder="Put Snowflake ID here (eg. 1263785187301658678)" label-position="left" label-width="110px" mb-2 label-align="right" />
20+
<c-input-text v-model:value="inputEpoch" label="Epoch" placeholder="Put Epoch Timestamp here (optional, eg. 1420070400000)" label-position="left" label-width="110px" mb-2 label-align="right" />
21+
22+
<n-divider />
23+
24+
<InputCopyable
25+
label="Local date"
26+
v-bind="inputProps"
27+
:value="inputEpoch ? new Date(extractTimestamp(BigInt(inputId.valueOf()), BigInt(inputEpoch.valueOf()))).toLocaleString() : ''"
28+
placeholder="Epoch Timestamp will be here..."
29+
label-position="left" label-width="110px" mb-2 label-align="right"
30+
/>
31+
32+
<InputCopyable
33+
label="Timestamp"
34+
v-bind="inputProps"
35+
:value="inputEpoch ? new Date(extractTimestamp(BigInt(inputId.valueOf()), BigInt(inputEpoch.valueOf()))).getTime() : ''"
36+
placeholder="Epoch Timestamp will be here..."
37+
label-position="left" label-width="110px" mb-2 label-align="right"
38+
/>
39+
40+
<InputCopyable
41+
label="Machine ID"
42+
v-bind="inputProps"
43+
:value="extractMachineId(BigInt(inputId.valueOf()))"
44+
placeholder="Machine ID will be here..."
45+
label-position="left" label-width="110px" mb-2 label-align="right"
46+
/>
47+
48+
<InputCopyable
49+
label="Sequence"
50+
v-bind="inputProps"
51+
:value="extractId(BigInt(inputId.valueOf()))"
52+
placeholder="Sequence number will be here..."
53+
label-position="left" label-width="110px" mb-2 label-align="right"
54+
/>
55+
</c-card>
56+
</div>
57+
</template>

0 commit comments

Comments
 (0)