Skip to content

Commit f7b024a

Browse files
committed
feat(new tool): Mongo ObjectId DateTime Converter
Fix CorentinTh#789
1 parent e1b4f9a commit f7b024a

File tree

6 files changed

+137
-0
lines changed

6 files changed

+137
-0
lines changed

components.d.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -126,10 +126,12 @@ declare module '@vue/runtime-core' {
126126
MenuLayout: typeof import('./src/components/MenuLayout.vue')['default']
127127
MetaTagGenerator: typeof import('./src/tools/meta-tag-generator/meta-tag-generator.vue')['default']
128128
MimeTypes: typeof import('./src/tools/mime-types/mime-types.vue')['default']
129+
MongoObjectidConverter: typeof import('./src/tools/mongo-objectid-converter/mongo-objectid-converter.vue')['default']
129130
NavbarButtons: typeof import('./src/components/NavbarButtons.vue')['default']
130131
NCode: typeof import('naive-ui')['NCode']
131132
NCollapseTransition: typeof import('naive-ui')['NCollapseTransition']
132133
NConfigProvider: typeof import('naive-ui')['NConfigProvider']
134+
NDatePicker: typeof import('naive-ui')['NDatePicker']
133135
NDivider: typeof import('naive-ui')['NDivider']
134136
NEllipsis: typeof import('naive-ui')['NEllipsis']
135137
NFormItem: typeof import('naive-ui')['NFormItem']

src/tools/index.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import { tool as asciiTextDrawer } from './ascii-text-drawer';
66

77
import { tool as textToUnicode } from './text-to-unicode';
88
import { tool as safelinkDecoder } from './safelink-decoder';
9+
import { tool as mongoObjectidConverter } from './mongo-objectid-converter';
910
import { tool as pdfSignatureChecker } from './pdf-signature-checker';
1011
import { tool as numeronymGenerator } from './numeronym-generator';
1112
import { tool as macAddressGenerator } from './mac-address-generator';
@@ -148,6 +149,7 @@ export const toolsByCategory: ToolCategory[] = [
148149
dockerRunToDockerComposeConverter,
149150
xmlFormatter,
150151
yamlViewer,
152+
mongoObjectidConverter,
151153
],
152154
},
153155
{
Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
import { Database } from '@vicons/tabler';
2+
import { defineTool } from '../tool';
3+
4+
export const tool = defineTool({
5+
name: 'MongoDB ObjectId Converter',
6+
path: '/mongo-objectid-converter',
7+
description: 'Convert between MongoDB ObjectId and internal timestamp',
8+
keywords: ['mongo', 'objectid', 'converter', 'timestamp'],
9+
component: () => import('./mongo-objectid-converter.vue'),
10+
icon: Database,
11+
createdAt: new Date('2024-08-15'),
12+
});
Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,30 @@
1+
import { describe, expect, it } from 'vitest';
2+
import { dateFromObjectId, generateMongoFilter, objectIdFromDate, objectIdSyntaxFromDate } from './mongo-objectid-converter.service';
3+
4+
describe('mongo-objectid-converter', () => {
5+
describe('objectIdFromDate', () => {
6+
it('convert a Date to ObjectId', () => {
7+
expect(objectIdFromDate(new Date(Date.UTC(2024, 0, 1)))).to.eql('659200800000000000000000');
8+
expect(objectIdFromDate(new Date(Date.UTC(2024, 0, 1, 12, 12, 12)))).to.eql('6592ac1c0000000000000000');
9+
});
10+
});
11+
describe('objectIdSyntaxFromDate', () => {
12+
it('convert a Date to ObjectId', () => {
13+
expect(objectIdSyntaxFromDate(new Date(Date.UTC(2024, 0, 1)))).to.eql('ObjectId("659200800000000000000000")');
14+
});
15+
});
16+
describe('dateFromObjectId', () => {
17+
it('convert an ObjectId to Date', () => {
18+
expect(dateFromObjectId('659200800000000000000000')).to.eql(new Date(Date.UTC(2024, 0, 1)));
19+
expect(dateFromObjectId('6592ac1c0000000000000000')).to.eql(new Date(Date.UTC(2024, 0, 1, 12, 12, 12)));
20+
});
21+
});
22+
describe('generateMongoFilter', () => {
23+
it('convert a date to mongo query', () => {
24+
expect(generateMongoFilter({
25+
date: new Date(Date.UTC(2024, 0, 1, 12, 12, 12)),
26+
tableName: 'comments',
27+
})).to.eql('db.comments.find({_id: {$gt: ObjectId("6592ac1c0000000000000000")}})');
28+
});
29+
});
30+
});
Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,23 @@
1+
export function objectIdFromDate(date: Date) {
2+
return `${Math.floor(date.getTime() / 1000).toString(16)}0000000000000000`;
3+
};
4+
5+
export function objectIdSyntaxFromDate(date: Date) {
6+
return `ObjectId("${objectIdFromDate(date)}")`;
7+
};
8+
9+
export function generateMongoFilter(
10+
{
11+
tableName, date, operator = 'gt',
12+
}:
13+
{
14+
tableName: string
15+
date: Date
16+
operator?: 'gt' | 'lt'
17+
}) {
18+
return `db.${tableName}.find({_id: {$${operator}: ObjectId("${objectIdFromDate(date)}")}})`;
19+
}
20+
21+
export function dateFromObjectId(objectId: string) {
22+
return new Date(Number.parseInt(objectId.substring(0, 8), 16) * 1000);
23+
};
Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
<script setup lang="ts">
2+
import { dateFromObjectId, generateMongoFilter, objectIdFromDate, objectIdSyntaxFromDate } from './mongo-objectid-converter.service';
3+
import { withDefaultOnError } from '@/utils/defaults';
4+
5+
const currentTimeZone = Intl.DateTimeFormat().resolvedOptions().timeZone;
6+
7+
const objectIdInput = ref(objectIdFromDate(new Date()));
8+
const dateOutput = computed(() =>
9+
withDefaultOnError(() => dateFromObjectId(objectIdInput.value), 'Invalid ObjectId'),
10+
);
11+
12+
const dateInput = ref(Date.now());
13+
const dateValue = computed(() => new Date(dateInput.value));
14+
const tableName = ref('tbl');
15+
const objectIdOutput = computed(() =>
16+
withDefaultOnError(() => objectIdFromDate(dateValue.value), 'Invalid Date'),
17+
);
18+
const objectIdSyntaxOutput = computed(() =>
19+
withDefaultOnError(() => objectIdSyntaxFromDate(dateValue.value), 'Invalid Date'),
20+
);
21+
const objectIdQueryOutput = computed(() =>
22+
withDefaultOnError(() => generateMongoFilter({ date: dateValue.value, tableName: tableName.value }), 'Invalid Date'),
23+
);
24+
const objectIdUTCDate = computed(() =>
25+
dateValue.value.toISOString(),
26+
);
27+
</script>
28+
29+
<template>
30+
<c-card :title="`ObjectId to Date (${currentTimeZone})`">
31+
<c-input-text
32+
v-model:value="objectIdInput"
33+
placeholder="Put your ObjectId here..."
34+
label="ObjectId to encode"
35+
raw-text
36+
mb-5
37+
/>
38+
39+
<n-divider />
40+
41+
<textarea-copyable
42+
:value="dateOutput instanceof Date ? dateOutput.toLocaleString(undefined, { timeZoneName: 'short' }) : dateOutput"
43+
/>
44+
<textarea-copyable
45+
:value="dateOutput instanceof Date ? dateOutput.toISOString() : dateOutput"
46+
/>
47+
</c-card>
48+
49+
<c-card :title="`Date to ObjectId (${currentTimeZone})`">
50+
<n-form-item label="Date and time" label-placement="left" mb-2 flex-1>
51+
<n-date-picker v-model:value="dateInput" type="datetime" />
52+
</n-form-item>
53+
54+
<c-input-text
55+
v-model:value="tableName"
56+
placeholder="Put your Table Name here..."
57+
label="Table Name"
58+
label-position="left"
59+
raw-text
60+
mb-5
61+
/>
62+
63+
<textarea-copyable :value="objectIdUTCDate" />
64+
<textarea-copyable :value="objectIdOutput" />
65+
<textarea-copyable :value="objectIdSyntaxOutput" />
66+
<textarea-copyable :value="objectIdQueryOutput" />
67+
</c-card>
68+
</template>

0 commit comments

Comments
 (0)