diff --git a/package-lock.json b/package-lock.json
index 8916a54..9de3fe5 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "dummyi",
- "version": "0.1.0",
+ "version": "0.2.2",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "dummyi",
- "version": "0.1.0",
+ "version": "0.2.2",
"dependencies": {
"@douyinfe/semi-next": "^2.51.0",
"@douyinfe/semi-ui": "^2.51.0",
diff --git a/package.json b/package.json
index d7ada64..e0590dc 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "dummyi",
- "version": "0.2.2",
+ "version": "0.2.3",
"private": true,
"scripts": {
"dev": "next dev",
diff --git a/scripts/addNewGenerator.ts b/scripts/addNewGenerator.ts
index e81710c..5403898 100644
--- a/scripts/addNewGenerator.ts
+++ b/scripts/addNewGenerator.ts
@@ -106,7 +106,7 @@ export const ${generatorName}GeneratorDefaultOptions:${generatorName}GeneratorOp
// -------------------------------------------------------------------------------------------------------------
// generate method
-export const generate = (options: any): GenerateResult => {
+export const generate = (options: ${generatorName}GeneratorOptions): GenerateResult => {
// TODO: implement your own generate method here
return {
@@ -125,9 +125,9 @@ export const ${generatorName}GeneratorOptionsComponent: React.FunctionComponent<
// TODO: implement your own options component here
return (
-
+ <>
NOT IMPLEMENTED
-
+ >
);
}`;
}
diff --git a/src/components/DevTools/src/GenerateResultsPreviewer.tsx b/src/components/DevTools/src/GenerateResultsPreviewer.tsx
index 595aa5a..5c90700 100644
--- a/src/components/DevTools/src/GenerateResultsPreviewer.tsx
+++ b/src/components/DevTools/src/GenerateResultsPreviewer.tsx
@@ -77,7 +77,7 @@ export const GenerateResultsPreviewer: React.FunctionComponent
-
+
{formatType}
{isError && ERROR}
diff --git a/src/components/InputPanel/src/InputPanel.tsx b/src/components/InputPanel/src/InputPanel.tsx
index 3f66bee..bdc375e 100644
--- a/src/components/InputPanel/src/InputPanel.tsx
+++ b/src/components/InputPanel/src/InputPanel.tsx
@@ -23,7 +23,7 @@ export const InputPanel: React.FunctionComponent = () => {
setPanelHeight(containerHeight);
- if (containerWidth > 1000) {
+ if (containerWidth > 900) {
setComponentSize(ComponentSize.LARGE);
} else if (containerWidth > 550) {
setComponentSize(ComponentSize.MEDIUM);
diff --git a/src/components/InputPanel/src/components/DataTypeSelectModal.tsx b/src/components/InputPanel/src/components/DataTypeSelectModal.tsx
index 72a0037..2200c79 100644
--- a/src/components/InputPanel/src/components/DataTypeSelectModal.tsx
+++ b/src/components/InputPanel/src/components/DataTypeSelectModal.tsx
@@ -21,7 +21,7 @@ export interface DataTypeSelectModalProps {
export const DataTypeSelectModal: React.FunctionComponent = ({...props}) => {
const intl = useIntl();
- const {Title} = Typography;
+ const {Title, Text} = Typography;
const dispatch = useDispatch();
const [searchText, setSearchText] = React.useState(null);
const data = useMemo(() => getGeneratorList(searchText, intl), [intl, searchText]);
@@ -34,7 +34,7 @@ export const DataTypeSelectModal: React.FunctionComponent {
- dispatch(doChangeDataType(currentTargetDataFieldId,item.type));
+ dispatch(doChangeDataType(currentTargetDataFieldId, item.type));
onCancel();
}
@@ -106,7 +106,9 @@ export const DataTypeSelectModal: React.FunctionComponent (
- {example}
+
+ {example}
+
))
}
diff --git a/src/components/Utils/src/OptionsDatetimePicker.tsx b/src/components/Utils/src/OptionsDatetimePicker.tsx
new file mode 100644
index 0000000..cf6a92e
--- /dev/null
+++ b/src/components/Utils/src/OptionsDatetimePicker.tsx
@@ -0,0 +1,55 @@
+import React from "react";
+import {ErrorTooltip, InfoTooltip} from "@/components/Utils";
+import {useIntl} from "@/locale";
+import {isNullOrWhiteSpace} from "@/utils/stringUtils";
+import {DatePicker} from "@douyinfe/semi-ui";
+import {hasValue} from "@/utils/typeUtils";
+
+export interface OptionsDatetimePickerProps {
+ label: string | React.ReactNode;
+ type?: "date" | "dateTime" | "dateRange" | "dateTimeRange";
+ infoTooltip?: string | React.ReactNode;
+ errorMessage?: string;
+ value: string | number | Date | string[] | number[] | Date[];
+ onChange: (value: any) => void;
+ style?: React.CSSProperties;
+ required?: boolean;
+}
+
+export const OptionsDatetimePicker: React.FunctionComponent = ({...props}) => {
+ const {label, type, infoTooltip, errorMessage, value, style, onChange, required} = props;
+ const intl = useIntl();
+
+ // Add a new useState to manage the validation error message
+ const [validationError, setValidationError] = React.useState();
+
+ // Add effect to validate value when it changes or when required status changes
+ React.useEffect(() => {
+ if (required && !hasValue(value)) {
+ setValidationError(intl.formatMessage({id: 'error.input.isRequired'})); // Set default required error message or use props.errorMessage
+ } else {
+ setValidationError(undefined); // Clear error message when input is valid
+ }
+ }, [value, required]);
+
+ return (
+
+
+ {label}
+ {infoTooltip &&
+ {infoTooltip}
+ }
+
+
+ onChange(dateString)}
+ value={value}
+ style={style}
+ validateStatus={!isNullOrWhiteSpace(validationError || errorMessage) ? 'error' : 'default'}
+ />
+
+
+ )
+}
\ No newline at end of file
diff --git a/src/components/Utils/src/OptionsSwitch.tsx b/src/components/Utils/src/OptionsSwitch.tsx
index 05eb65d..9c4acd7 100644
--- a/src/components/Utils/src/OptionsSwitch.tsx
+++ b/src/components/Utils/src/OptionsSwitch.tsx
@@ -27,7 +27,7 @@ export const OptionsSwitch: React.FunctionComponent = ({...p
diff --git a/src/constants/enums.ts b/src/constants/enums.ts
index 918d080..f0a0ab6 100644
--- a/src/constants/enums.ts
+++ b/src/constants/enums.ts
@@ -1,4 +1,3 @@
-
// export format
export enum ExportFormatCategory {
FILE_TYPES = "file_types",
@@ -18,17 +17,18 @@ export enum ExportFormat {
export enum ValueType {
STRING = "string",
- TEXT= "text",
+ TEXT = "text",
ONE_BIT = "1bit",
INT = "integer",
BIGINT = "bigint",
DOUBLE = "double",
BOOLEAN = "boolean",
INT_LIST = "int_list",
- STRING_LIST = "string_list"
+ STRING_LIST = "string_list",
+ DATE_TIME = "date_time"
}
-export enum ExportProcessStage{
+export enum ExportProcessStage {
PREVIEW = "preview",
GENERATING = "generating",
COMPLETED = "completed",
@@ -36,14 +36,19 @@ export enum ExportProcessStage{
// data types
export enum DataTypeCategory {
- ALL= "all",
+ ALL = "all",
BASIC = "basic",
PERSON = "person",
NETWORK = "network",
COMMERCE = "commerce",
+ DATETIME = "datetime"
}
export enum DataType {
+ BIRTHDAY = "birthday",
+ MONTH = "month",
+ WEEKDAY = "weekday",
+ DATETIME = "datetime",
URL = "url",
DOMAINSUFFIX = "domainsuffix",
DOMAINNAME = "domainname",
@@ -81,18 +86,18 @@ export enum Locales {
JA_JP = "ja-JP",
}
-export enum ComponentSize{
+export enum ComponentSize {
SMALL = "small",
MEDIUM = "medium",
LARGE = "large",
}
-export enum PreviewType{
+export enum PreviewType {
TABLE = "table",
RAW = "raw"
}
-export enum CollectionNodeType{
+export enum CollectionNodeType {
COLLECTION = "collection",
SCHEMA = "schema"
}
@@ -102,7 +107,7 @@ export enum EndOfLineChars {
CRLF = '\r\n'
}
-export enum Sex{
+export enum Sex {
ALL = "all",
MALE = "male",
FEMALE = "female"
diff --git a/src/core/formatters/CSharp/CSharp.tsx b/src/core/formatters/CSharp/CSharp.tsx
index cff70b9..ed4d198 100644
--- a/src/core/formatters/CSharp/CSharp.tsx
+++ b/src/core/formatters/CSharp/CSharp.tsx
@@ -72,6 +72,9 @@ export const format = (request: FormatRequest): string => {
case ValueType.ONE_BIT:
fieldType = `int${field.emptyRate !== 0 ? "?" : ""}`;
break;
+ case ValueType.DATE_TIME:
+ fieldType = `DateTime${field.emptyRate !== 0 ? "?" : ""}`
+ break;
// Add more cases as necessary
}
csharpCode += ` public ${fieldType} ${field.fieldName} { get; set; }\n`;
diff --git a/src/core/formatters/CSharp/CSharpFormatterUtils.ts b/src/core/formatters/CSharp/CSharpFormatterUtils.ts
index f3cfed2..8eea719 100644
--- a/src/core/formatters/CSharp/CSharpFormatterUtils.ts
+++ b/src/core/formatters/CSharp/CSharpFormatterUtils.ts
@@ -26,7 +26,20 @@ export function formatValueForCSharp(generateResult: GenerateResult, valueType:
return `new List { ${value.join(", ")} }`
case ValueType.STRING_LIST:
return `new List { ${value.map(item => `"${item}"`).join(', ')})} }`
+ case ValueType.DATE_TIME:
+ return `DateTime.Parse("${toCSharpDateTimeFormat(value)}")`
default:
return 'null'; // Or some other default case
}
+}
+
+export function toCSharpDateTimeFormat(date: Date): string {
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份是从0开始的
+ const day = String(date.getDate()).padStart(2, '0');
+
+ const hours = String(date.getHours()).padStart(2, '0');
+ const minutes = String(date.getMinutes()).padStart(2, '0');
+
+ return `${year}-${month}-${day} ${hours}:${minutes}`;
}
\ No newline at end of file
diff --git a/src/core/formatters/Sql/Sql.tsx b/src/core/formatters/Sql/Sql.tsx
index 161922c..86d10df 100644
--- a/src/core/formatters/Sql/Sql.tsx
+++ b/src/core/formatters/Sql/Sql.tsx
@@ -61,14 +61,16 @@ const addCreateTableColumn = (field: DataField, sqlType: SqlType) => {
fieldType = (sqlType === SqlType.ORACLE || sqlType === SqlType.IBMDB2) ? "CLOB" : "TEXT";
break;
case ValueType.ONE_BIT:
- fieldType = "TINYINT(1)";
- break;
case ValueType.BOOLEAN:
fieldType = "TINYINT(1)";
break;
case ValueType.BIGINT:
fieldType = "BIGINT";
break;
+ case ValueType.DATE_TIME: // Add this line
+ // Define default DATETIME format, then override per SQL type if necessary
+ fieldType = "DATETIME";
+ break;
default:
fieldType = "VARCHAR(255)";
break;
@@ -77,23 +79,29 @@ const addCreateTableColumn = (field: DataField, sqlType: SqlType) => {
// Apply SQL type-specific modifications
switch (sqlType) {
case SqlType.ORACLE:
- // Oracle-specific adaptations, e.g., use NUMBER instead of INT
+ // Oracle-specific adaptations
if (fieldType === "INT") {
fieldType = "NUMBER";
} else if (fieldType === "TINYINT(1)") {
fieldType = "NUMBER(1)";
+ } else if (fieldType === "DATETIME") { // Add this line
+ fieldType = "TIMESTAMP"; // Or DATE, depending on your needs
}
break;
case SqlType.POSTGRES:
- // Postgres-specific adaptations, e.g., use BOOLEAN instead of TINYINT(1)
+ // Postgres-specific adaptations
if (fieldType === "TINYINT(1)") {
fieldType = "BOOLEAN";
+ } else if (fieldType === "DATETIME") { // Add this line
+ fieldType = "TIMESTAMP"; // Or TIMESTAMP WITHOUT TIME ZONE, depending on your needs
}
break;
case SqlType.SQLITE:
- // SQLite uses a more dynamic type system
+ // SQLite adaptations
if (fieldType === "TINYINT(1)") {
fieldType = "INTEGER";
+ } else if (fieldType === "DATETIME") { // Add this line
+ fieldType = "TEXT"; // SQLite uses TEXT for date and time types
}
break;
// Add cases for other SQL types as necessary
@@ -116,7 +124,29 @@ const formatValueForSQL = (value: any, sqlType: SqlType, valueType: ValueType):
case ValueType.INT_LIST:
return `'${value.join(", ")}'`
case ValueType.STRING_LIST:
- return `'${value.map(item => `"${item}"`).join(', ')}'`
+ return `'${value.map((item: string): string => `"${item}"`).join(', ')}'`
+ case ValueType.DATE_TIME:
+ let formattedDate: string;
+ // Assuming value is a JavaScript Date object for simplicity
+ const date = (value instanceof Date) ? value : new Date(value);
+
+ switch (sqlType) {
+ case SqlType.ORACLE:
+ // Oracle format: 'YYYY-MM-DD HH24:MI:SS'
+ formattedDate = `${date.getFullYear()}-${String(date.getMonth() + 1).padStart(2, '0')}-${String(date.getDate()).padStart(2, '0')} ${String(date.getHours()).padStart(2, '0')}:${String(date.getMinutes()).padStart(2, '0')}:${String(date.getSeconds()).padStart(2, '0')}`;
+ break;
+ case SqlType.POSTGRES:
+ // PostgreSQL format: 'YYYY-MM-DD HH:MM:SS'
+ formattedDate = date.toISOString().slice(0, 19).replace('T', ' ');
+ break;
+ // Add additional cases for different SQL types as needed
+ default:
+ // Default to ISO format 'YYYY-MM-DD HH:MM:SS'
+ formattedDate = date.toISOString().slice(0, 19).replace('T', ' ');
+ break;
+ }
+
+ return `'${formattedDate}'`;
default:
return value;
}
diff --git a/src/core/formatters/Typescript/Typescript.tsx b/src/core/formatters/Typescript/Typescript.tsx
index 5d5f286..7a645d1 100644
--- a/src/core/formatters/Typescript/Typescript.tsx
+++ b/src/core/formatters/Typescript/Typescript.tsx
@@ -63,6 +63,9 @@ export const format = (request: FormatRequest): string => {
case ValueType.STRING_LIST:
fieldType = 'string[]'
break;
+ case ValueType.DATE_TIME:
+ fieldType = "Date"
+ break;
}
output += ` ${field.fieldName}${field.emptyRate !== 0 ? "?" : ""}: ${fieldType};\n`;
});
diff --git a/src/core/generators/Birthday/Birthday.tsx b/src/core/generators/Birthday/Birthday.tsx
new file mode 100644
index 0000000..d7912d1
--- /dev/null
+++ b/src/core/generators/Birthday/Birthday.tsx
@@ -0,0 +1,143 @@
+import React from "react";
+import {GenerateResult, GeneratorOptionsComponentInterface} from "@/types/generator";
+import {DateTimeFormat, DateTimeFormatSelectOptions, formatDateTime} from "@/core/generators/DateTime/DateTime";
+import {OptionsNumberInput, OptionsSelect, SelectOption} from "@/components/Utils";
+import {FormattedMessage} from "@/locale";
+import {faker} from "@faker-js/faker";
+import {ValueType} from "@/constants/enums";
+
+// -------------------------------------------------------------------------------------------------------------
+// types
+
+export enum BirthdayGeneratorMode {
+ AGE = "age",
+ YEAR = "year"
+}
+
+export interface BirthdayGeneratorOptions {
+ format: DateTimeFormat;
+ mode: BirthdayGeneratorMode;
+ minAge: number;
+ maxAge: number;
+ fromYear: number;
+ toYear: number;
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// default options
+export const BirthdayGeneratorDefaultOptions: BirthdayGeneratorOptions = {
+ format: DateTimeFormat.DATETIME,
+ mode: BirthdayGeneratorMode.AGE,
+ minAge: 1,
+ maxAge: 80,
+ fromYear: 1960,
+ toYear: 2000,
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// generate method
+export const generate = (options: BirthdayGeneratorOptions): GenerateResult => {
+
+ const value = faker.date.birthdate({
+ mode: options.mode,
+ min: options.mode === BirthdayGeneratorMode.AGE ? options.minAge : options.fromYear,
+ max: options.mode === BirthdayGeneratorMode.AGE ? options.maxAge : options.toYear,
+ refDate: Date.now()
+ })
+ const output = formatDateTime(value, options.format);
+
+ return {
+ value: output,
+ stringValue: (output instanceof Date) ? output.toISOString() : output.toString()
+ };
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// options component
+export const BirthdayGeneratorOptionsComponent: React.FunctionComponent = ({...props}) => {
+ const {options, handleOptionValueChange} = props as {
+ options: BirthdayGeneratorOptions,
+ handleOptionValueChange: typeof props.handleOptionValueChange
+ };
+
+ const handleChangeFormat = (format: DateTimeFormat) => {
+ if (format === DateTimeFormat.TIMESTAMP) {
+ handleOptionValueChange("format", format, ValueType.INT);
+ } else if (format === DateTimeFormat.TEXT) {
+ handleOptionValueChange("format", format, ValueType.STRING);
+ } else if (format === DateTimeFormat.DATETIME) {
+ handleOptionValueChange("format", format, ValueType.DATE_TIME);
+ }
+ }
+
+ return (
+ <>
+ }
+ selectOptions={BirthdayGeneratorModeSelectOptions}
+ value={options.mode}
+ onChange={(v) => handleOptionValueChange("mode", v)}
+ />
+
+ {options.mode === BirthdayGeneratorMode.AGE && <>
+ }
+ value={options.minAge}
+ onChange={(v) => handleOptionValueChange("minAge", v)}
+ style={{width: "70px"}}
+ min={0}
+ max={options.maxAge}
+ />
+
+ }
+ value={options.maxAge}
+ onChange={(v) => handleOptionValueChange("maxAge", v)}
+ style={{width: "70px"}}
+ min={options.minAge}
+ max={150}
+ />
+ >}
+
+
+ {options.mode === BirthdayGeneratorMode.YEAR && <>
+ }
+ value={options.fromYear}
+ onChange={(v) => handleOptionValueChange("fromYear", v)}
+ style={{width: "90px"}}
+ min={1000}
+ max={options.toYear}
+ />
+
+ }
+ value={options.toYear}
+ onChange={(v) => handleOptionValueChange("toYear", v)}
+ style={{width: "100px"}}
+ min={options.toYear}
+ max={2500}
+ />
+ >}
+
+ }
+ selectOptions={DateTimeFormatSelectOptions}
+ value={options.format}
+ onChange={handleChangeFormat}
+ style={{width: "200px"}}
+ />
+
+ >
+ );
+}
+
+const BirthdayGeneratorModeSelectOptions: SelectOption[] = [
+ {
+ label: ,
+ value: BirthdayGeneratorMode.AGE
+ }, {
+ label: ,
+ value: BirthdayGeneratorMode.YEAR
+ }
+]
\ No newline at end of file
diff --git a/src/core/generators/Birthday/index.ts b/src/core/generators/Birthday/index.ts
new file mode 100644
index 0000000..f915ab9
--- /dev/null
+++ b/src/core/generators/Birthday/index.ts
@@ -0,0 +1,14 @@
+import {Generator} from "@/types/generator";
+import {DataType, DataTypeCategory, ValueType} from "@/constants/enums";
+import {BirthdayGeneratorDefaultOptions, BirthdayGeneratorOptionsComponent, generate} from "./Birthday";
+
+export const BirthdayGenerator: Generator = {
+ type: DataType.BIRTHDAY,
+ category: DataTypeCategory.PERSON,
+ generate: generate,
+ optionsComponent: BirthdayGeneratorOptionsComponent,
+ defaultOptions: BirthdayGeneratorDefaultOptions,
+ defaultValueType: ValueType.DATE_TIME,
+ exampleLines: ["1949-08-11T20:00:14.636Z", "-640186506999", "18-02-1968 20:14:50"]
+}
+
\ No newline at end of file
diff --git a/src/core/generators/DateTime/DateTime.tsx b/src/core/generators/DateTime/DateTime.tsx
new file mode 100644
index 0000000..ed66fe4
--- /dev/null
+++ b/src/core/generators/DateTime/DateTime.tsx
@@ -0,0 +1,189 @@
+import React from "react";
+import {GenerateResult, GeneratorOptionsComponentInterface} from "@/types/generator";
+import {OptionsSelect, SelectOption} from "@/components/Utils";
+import {FormattedMessage} from "@/locale";
+import {OptionsDatetimePicker} from "@/components/Utils/src/OptionsDatetimePicker";
+import {faker} from "@faker-js/faker";
+import {ValueType} from "@/constants/enums";
+import style from "@/core/generators/Boolean/Boolean.module.scss";
+import {Tag} from "@douyinfe/semi-ui";
+import {toDateTimeString} from "@/utils/typeUtils";
+
+// -------------------------------------------------------------------------------------------------------------
+// types
+export enum DateTimeTerms {
+ ANYTIME = "anytime",
+ BETWEEN = "between",
+ FUTURE = "future",
+ PAST = "past",
+ RECENT = "recent",
+ SOON = "soon"
+}
+
+export enum DateTimeFormat {
+ TEXT = "text",
+ TIMESTAMP = "timestamp",
+ DATETIME = "datetime"
+}
+
+export interface DateTimeGeneratorOptions {
+ terms: DateTimeTerms;
+ ref: Date | number | string;
+ format: DateTimeFormat;
+ timeRange: Date[] | number[] | string[];
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// default options
+export const DateTimeGeneratorDefaultOptions: DateTimeGeneratorOptions = {
+ terms: DateTimeTerms.ANYTIME,
+ ref: Date.now(),
+ format: DateTimeFormat.DATETIME,
+ timeRange: [new Date(2023, 0, 1), new Date()]
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// generate method
+export const generate = (options: DateTimeGeneratorOptions): GenerateResult => {
+ const {terms, ref, format} = options;
+
+ let value: Date;
+ const fakerOptions = {refDate: ref}
+
+ switch (terms) {
+ case DateTimeTerms.FUTURE:
+ value = faker.date.future(fakerOptions);
+ break;
+ case DateTimeTerms.PAST:
+ value = faker.date.past(fakerOptions);
+ break;
+ case DateTimeTerms.RECENT:
+ value = faker.date.recent(fakerOptions);
+ break;
+ case DateTimeTerms.SOON:
+ value = faker.date.soon(fakerOptions);
+ break;
+ case DateTimeTerms.BETWEEN:
+ value = faker.date.between({from: options.timeRange[0], to: options.timeRange[1]});
+ break;
+ default:
+ value = faker.date.anytime(fakerOptions);
+ }
+
+ const output = formatDateTime(value, format);
+
+ return {
+ value: output,
+ stringValue: (output instanceof Date) ? output.toISOString() : output.toString()
+ };
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// options component
+export const DateTimeGeneratorOptionsComponent: React.FunctionComponent = ({...props}) => {
+
+ const {options, handleOptionValueChange} = props as {
+ options: DateTimeGeneratorOptions,
+ handleOptionValueChange: typeof props.handleOptionValueChange
+ };
+
+ const handleChangeFormat = (format: DateTimeFormat) => {
+ if (format === DateTimeFormat.TIMESTAMP) {
+ handleOptionValueChange("format", format, ValueType.INT);
+ } else if (format === DateTimeFormat.TEXT) {
+ handleOptionValueChange("format", format, ValueType.STRING);
+ } else if (format === DateTimeFormat.DATETIME) {
+ handleOptionValueChange("format", format, ValueType.DATE_TIME);
+ }
+ }
+
+ return (
+ <>
+ }
+ selectOptions={DateTimeTermsSelectOptions}
+ value={options.terms}
+ onChange={(v) => handleOptionValueChange("terms", v)}
+ style={{width: "130px"}}
+ />
+
+ {
+ options.terms === DateTimeTerms.BETWEEN ? }
+ type={'dateTimeRange'}
+ value={options.timeRange}
+ onChange={(v) => handleOptionValueChange("timeRange", v)}
+ style={{width: "260px"}}
+ required
+ />
+ :
+ }
+ infoTooltip={}
+ type={'dateTime'}
+ value={options.ref}
+ onChange={(v) => handleOptionValueChange("ref", v)}
+ style={{width: "185px"}}
+ required
+ />
+ }
+
+ }
+ selectOptions={DateTimeFormatSelectOptions}
+ value={options.format}
+ onChange={handleChangeFormat}
+ style={{width: "200px"}}
+ />
+ >
+ );
+}
+
+export const formatDateTime = (date: Date, format: DateTimeFormat) => {
+ switch (format) {
+ case DateTimeFormat.DATETIME:
+ return date;
+ case DateTimeFormat.TIMESTAMP:
+ return date.getTime();
+ case DateTimeFormat.TEXT:
+ return toDateTimeString(date);
+ }
+}
+
+export const DateTimeTermsSelectOptions: SelectOption[] = Object.values(DateTimeTerms).map((term) => {
+ return {
+ value: term,
+ label:
+ };
+})
+
+export const DateTimeFormatSelectOptions: SelectOption[] = [
+ {
+ value: DateTimeFormat.DATETIME,
+ label:
+ <>
+ Date
+
+ >
+ },
+ {
+ value: DateTimeFormat.TIMESTAMP,
+ label:
+ <>
+ number
+
+ >
+ },
+ {
+ value: DateTimeFormat.TEXT,
+ label:
+ <>
+ string
+
+ >
+ },
+
+]
\ No newline at end of file
diff --git a/src/core/generators/DateTime/index.ts b/src/core/generators/DateTime/index.ts
new file mode 100644
index 0000000..1251e07
--- /dev/null
+++ b/src/core/generators/DateTime/index.ts
@@ -0,0 +1,14 @@
+import {Generator} from "@/types/generator";
+import {DataType, DataTypeCategory, ValueType} from "@/constants/enums";
+import {DateTimeGeneratorDefaultOptions, DateTimeGeneratorOptionsComponent, generate} from "./DateTime";
+
+export const DateTimeGenerator: Generator = {
+ type: DataType.DATETIME,
+ category: DataTypeCategory.DATETIME,
+ generate: generate,
+ optionsComponent: DateTimeGeneratorOptionsComponent,
+ defaultOptions: DateTimeGeneratorDefaultOptions,
+ defaultValueType: ValueType.DATE_TIME,
+ exampleLines: ["1725842513046", "29-01-2025 20:15:40", "13-06-2023 08:16:09"]
+}
+
\ No newline at end of file
diff --git a/src/core/generators/Month/Month.tsx b/src/core/generators/Month/Month.tsx
new file mode 100644
index 0000000..314b1b1
--- /dev/null
+++ b/src/core/generators/Month/Month.tsx
@@ -0,0 +1,49 @@
+import React from "react";
+import {GenerateResult, GeneratorOptionsComponentInterface} from "@/types/generator";
+import {OptionsSwitch} from "@/components/Utils/src/OptionsSwitch";
+import {FormattedMessage} from "@/locale";
+import {faker} from "@faker-js/faker";
+
+// -------------------------------------------------------------------------------------------------------------
+// types
+export interface MonthGeneratorOptions {
+ abbreviated: boolean;
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// default options
+export const MonthGeneratorDefaultOptions: MonthGeneratorOptions = {
+ abbreviated: false
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// generate method
+export const generate = (options: MonthGeneratorOptions): GenerateResult => {
+ const {abbreviated} = options;
+ const value = faker.date.month({abbreviated:abbreviated})
+ return {
+ value: value,
+ stringValue: value
+ };
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// options component
+export const MonthGeneratorOptionsComponent: React.FunctionComponent = ({...props}) => {
+ const {options, handleOptionValueChange} = props as {
+ options: MonthGeneratorOptions,
+ handleOptionValueChange: typeof props.handleOptionValueChange
+ };
+
+ // TODO: implement your own options component here
+ return (
+ <>
+ }
+ value={options.abbreviated}
+ onChange={(v) => handleOptionValueChange("abbreviated", v)}
+ />
+
+ >
+ );
+}
\ No newline at end of file
diff --git a/src/core/generators/Month/index.ts b/src/core/generators/Month/index.ts
new file mode 100644
index 0000000..825940f
--- /dev/null
+++ b/src/core/generators/Month/index.ts
@@ -0,0 +1,14 @@
+import {Generator} from "@/types/generator";
+import {DataType, DataTypeCategory, ValueType} from "@/constants/enums";
+import {MonthGeneratorDefaultOptions, MonthGeneratorOptionsComponent, generate} from "./Month";
+
+export const MonthGenerator: Generator = {
+ type: DataType.MONTH,
+ category: DataTypeCategory.DATETIME,
+ generate: generate,
+ optionsComponent: MonthGeneratorOptionsComponent,
+ defaultOptions: MonthGeneratorDefaultOptions,
+ defaultValueType: ValueType.STRING,
+ exampleLines: ["September", "Feb", "December"]
+}
+
\ No newline at end of file
diff --git a/src/core/generators/Number/Number.tsx b/src/core/generators/Number/Number.tsx
index 29a6119..f975519 100644
--- a/src/core/generators/Number/Number.tsx
+++ b/src/core/generators/Number/Number.tsx
@@ -95,18 +95,14 @@ export const NumberGeneratorOptionsComponent: React.FunctionComponent {
const newErrorMessages = {...errorMessages};
// min
- if (isNullOrWhiteSpace(options.min.toString())) {
- newErrorMessages.min = intl.formatMessage({id: 'dataType.number.min.errorMessage.empty'})
- } else if (options.min > options.max) {
+ if (options.min > options.max) {
newErrorMessages.min = intl.formatMessage({id: 'dataType.number.min.errorMessage.greaterThanMax'})
} else {
newErrorMessages.min = '';
}
// max
- if (isNullOrWhiteSpace(options.max.toString())) {
- newErrorMessages.max = intl.formatMessage({id: 'dataType.number.max.errorMessage.empty'})
- } else if (options.max < options.min) {
+ if (options.max < options.min) {
newErrorMessages.max = intl.formatMessage({id: 'dataType.number.max.errorMessage.lessThanMin'})
} else {
newErrorMessages.max = '';
diff --git a/src/core/generators/Weekday/Weekday.tsx b/src/core/generators/Weekday/Weekday.tsx
new file mode 100644
index 0000000..a9ed699
--- /dev/null
+++ b/src/core/generators/Weekday/Weekday.tsx
@@ -0,0 +1,47 @@
+import React from "react";
+import {GenerateResult, GeneratorOptionsComponentInterface} from "@/types/generator";
+import {OptionsSwitch} from "@/components/Utils/src/OptionsSwitch";
+import {FormattedMessage} from "@/locale";
+import {faker} from "@faker-js/faker";
+
+// -------------------------------------------------------------------------------------------------------------
+// types
+export interface WeekdayGeneratorOptions {
+ abbreviated: boolean;
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// default options
+export const WeekdayGeneratorDefaultOptions: WeekdayGeneratorOptions = {
+ abbreviated: false
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// generate method
+export const generate = (options: WeekdayGeneratorOptions): GenerateResult => {
+ const {abbreviated} = options;
+ const value = faker.date.weekday({abbreviated: abbreviated})
+ return {
+ value: value,
+ stringValue: value
+ };
+}
+
+// -------------------------------------------------------------------------------------------------------------
+// options component
+export const WeekdayGeneratorOptionsComponent: React.FunctionComponent = ({...props}) => {
+ const {options, handleOptionValueChange} = props as {
+ options: WeekdayGeneratorOptions,
+ handleOptionValueChange: typeof props.handleOptionValueChange
+ };
+
+ return (
+ <>
+ }
+ value={options.abbreviated}
+ onChange={(v) => handleOptionValueChange("abbreviated", v)}
+ />
+ >
+ );
+}
\ No newline at end of file
diff --git a/src/core/generators/Weekday/index.ts b/src/core/generators/Weekday/index.ts
new file mode 100644
index 0000000..8fe15f1
--- /dev/null
+++ b/src/core/generators/Weekday/index.ts
@@ -0,0 +1,14 @@
+import {Generator} from "@/types/generator";
+import {DataType, DataTypeCategory, ValueType} from "@/constants/enums";
+import {WeekdayGeneratorDefaultOptions, WeekdayGeneratorOptionsComponent, generate} from "./Weekday";
+
+export const WeekdayGenerator: Generator = {
+ type: DataType.WEEKDAY,
+ category: DataTypeCategory.DATETIME,
+ generate: generate,
+ optionsComponent: WeekdayGeneratorOptionsComponent,
+ defaultOptions: WeekdayGeneratorDefaultOptions,
+ defaultValueType: ValueType.STRING,
+ exampleLines: ["Wednesday", "Wed", "Thursday"]
+}
+
\ No newline at end of file
diff --git a/src/core/generators/index.ts b/src/core/generators/index.ts
index 8d6ffd1..7d98b22 100644
--- a/src/core/generators/index.ts
+++ b/src/core/generators/index.ts
@@ -1,3 +1,7 @@
+import {BirthdayGenerator} from "@/core/generators/Birthday";
+import {MonthGenerator} from "@/core/generators/Month";
+import {WeekdayGenerator} from "@/core/generators/Weekday";
+import {DateTimeGenerator} from "@/core/generators/DateTime";
import {UrlGenerator} from "@/core/generators/Url";
import {DomainSuffixGenerator} from "@/core/generators/DomainSuffix";
import {DomainNameGenerator} from "@/core/generators/DomainName";
@@ -19,6 +23,10 @@ import {CompanyNameGenerator} from "@/core/generators/CompanyName";
import {DataType} from "@/constants/enums";
export const generators = {
+ [DataType.BIRTHDAY]: BirthdayGenerator,
+ [DataType.MONTH]: MonthGenerator,
+ [DataType.WEEKDAY]: WeekdayGenerator,
+ [DataType.DATETIME]: DateTimeGenerator,
[DataType.URL]: UrlGenerator,
[DataType.DOMAINSUFFIX]: DomainSuffixGenerator,
[DataType.DOMAINNAME]: DomainNameGenerator,
diff --git a/src/locale/translations/en.ts b/src/locale/translations/en.ts
index bcbef4e..a298c96 100644
--- a/src/locale/translations/en.ts
+++ b/src/locale/translations/en.ts
@@ -86,6 +86,45 @@ export const en = {
// data types
+
+ // birthday
+ "dataType.birthday": "Birthday",
+ "dataType.birthday.mode":"Mode",
+ "dataType.birthday.mode.age":"Age",
+ "dataType.birthday.mode.year":"Year",
+ "dataType.birthday.mode.minAge":"Min. Age",
+ "dataType.birthday.mode.maxAge":"Max. Age",
+ "dataType.birthday.mode.fromYear":"From year",
+ "dataType.birthday.mode.toYear":"To year",
+
+ // month
+ "dataType.month": "Month",
+ "dataType.month.abbreviated": "Abbreviated",
+
+ // weekday
+ "dataType.weekday": "Weekday",
+ "dataType.weekday.abbreviated": "Abbreviated",
+
+ // datetime
+ "dataType.datetime": "DateTime",
+ "dataType.datetime.terms": "Terms",
+ "dataType.datetime.terms.anytime": "Anytime",
+ "dataType.datetime.terms.between": "Between",
+ "dataType.datetime.terms.future": "Future",
+ "dataType.datetime.terms.past": "Past",
+ "dataType.datetime.terms.recent": "Recent past",
+ "dataType.datetime.terms.soon": "Soon",
+ "dataType.datetime.ref": "Reference date",
+ "dataType.datetime.ref.tooltip": "The date to use as reference point",
+ "dataType.datetime.format": "Format",
+ "dataType.datetime.format.text": "Text",
+ "dataType.datetime.format.timestamp": "Timestamp",
+ "dataType.datetime.format.datetime": "DateTime",
+ "dataType.datetime.timeRange": "Range",
+
+ // anytime
+ "dataType.anytime": "Anytime",
+
// url
"dataType.url": "Url",
"dataType.url.appendSlash.label": "Slash",
@@ -159,9 +198,6 @@ export const en = {
"dataType.number.max.errorMessage.empty": "Max. value cannot be empty",
"dataType.number.max.errorMessage.lessThanMin": "Max. value cannot be less than min. value",
- // dateTime
- "dataType.dateTime": "Date time",
-
// boolean
"dataType.boolean": "Boolean",
"dataType.boolean.true.label": "Prob of True",
@@ -195,6 +231,7 @@ export const en = {
"dataType.category.person": "Person",
"dataType.category.commerce": "Commerce",
"dataType.category.network": "Network",
+ "dataType.category.datetime": "Datetime",
// -------------------------------------------------------------------------------------------------------------
// pages
diff --git a/src/locale/translations/jaJP.ts b/src/locale/translations/jaJP.ts
index 5a73c9f..4800825 100644
--- a/src/locale/translations/jaJP.ts
+++ b/src/locale/translations/jaJP.ts
@@ -86,6 +86,30 @@ export const jaJP = {
// data types
+
+
+
+
+
+
+ // birthday
+ "dataType.birthday": "Birthday",
+
+ // month
+ "dataType.month": "Month",
+
+ // weekday
+ "dataType.weekday": "Weekday",
+
+ // datetimerange
+ "dataType.datetimerange": "DateTimeRange",
+
+ // datetime
+ "dataType.datetime": "DateTime",
+
+ // anytime
+ "dataType.anytime": "Anytime",
+
// url
"dataType.url": "URL",
"dataType.url.appendSlash.label": "スラッシュ",
diff --git a/src/locale/translations/zhCN.ts b/src/locale/translations/zhCN.ts
index 2cdb78d..7438930 100644
--- a/src/locale/translations/zhCN.ts
+++ b/src/locale/translations/zhCN.ts
@@ -83,6 +83,41 @@ export const zhCN = {
// -------------------------------------------------------------------------------------------------------------
// data types
+
+ // birthday
+ "dataType.birthday": "生日",
+ "dataType.birthday.mode":"模式",
+ "dataType.birthday.mode.age":"年龄",
+ "dataType.birthday.mode.year":"出生年份",
+ "dataType.birthday.mode.minAge":"最小年龄",
+ "dataType.birthday.mode.maxAge":"最大年龄",
+ "dataType.birthday.mode.fromYear":"最小年份",
+ "dataType.birthday.mode.toYear":"最大年份",
+
+ // month
+ "dataType.month": "月份",
+ "dataType.month.abbreviated": "缩写",
+
+ // weekday
+ "dataType.weekday": "星期",
+ "dataType.weekday.abbreviated": "缩写",
+
+ // datetime
+ "dataType.datetime": "日期时间",
+ "dataType.datetime.terms": "条件",
+ "dataType.datetime.terms.anytime": "任意时间",
+ "dataType.datetime.terms.between": "区间",
+ "dataType.datetime.terms.future": "未来",
+ "dataType.datetime.terms.past": "过去",
+ "dataType.datetime.terms.recent": "不久之前",
+ "dataType.datetime.terms.soon": "不久之后",
+ "dataType.datetime.ref": "参考日期",
+ "dataType.datetime.ref.tooltip": "用于生成数据的参考日期",
+ "dataType.datetime.format": "格式",
+ "dataType.datetime.format.text": "文本",
+ "dataType.datetime.format.timestamp": "时间戳",
+ "dataType.datetime.format.datetime": "Date对象",
+ "dataType.datetime.timeRange": "区间",
// url
"dataType.url": "网址",
@@ -157,9 +192,6 @@ export const zhCN = {
"dataType.number.max.errorMessage.empty": "最大值不能为空",
"dataType.number.max.errorMessage.lessThanMin": "最大值不能小于最小值",
- // dateTime
- "dataType.dateTime": "日期时间",
-
// boolean
"dataType.boolean": "布尔值",
"dataType.boolean.true.label": "真值概率",
@@ -193,6 +225,7 @@ export const zhCN = {
"dataType.category.person": "人物",
"dataType.category.commerce": "商业",
"dataType.category.network": "网络",
+ "dataType.category.datetime": "时间",
// -------------------------------------------------------------------------------------------------------------
// pages
diff --git a/src/utils/formatterUtils.ts b/src/utils/formatterUtils.ts
index ad475d2..4e1f73b 100644
--- a/src/utils/formatterUtils.ts
+++ b/src/utils/formatterUtils.ts
@@ -1,5 +1,5 @@
import {FormatRequest, Formatter} from "@/types/formatter";
-import {ExportFormat} from "@/constants/enums";
+import {ExportFormat, ValueType} from "@/constants/enums";
import {formatters} from "@/core/formatters";
import {langs} from '@uiw/codemirror-extensions-langs';
import {DataFieldList} from "@/types/generator";
@@ -103,6 +103,8 @@ export function toJsonListStringWithoutQuotes(fields: DataFieldList, sortedField
if (Array.isArray(value)) { // 处理数组格式
const elements = value.map(element => convert(element, indent + 2));
return `[\n${nextIndentSpace}${elements.join(`,\n${nextIndentSpace}`)}\n${indentSpace}]`;
+ } else if (value instanceof Date) {
+ return `new Date("${toISOString(value)}")`
} else if (typeof value === 'object' && value !== null) { // 处理对象格式
const entries = Object.entries(value).map(([key, val]) => {
const formattedValue = convert(val, indent + 2);
@@ -137,3 +139,19 @@ export function toJsonListStringWithoutQuotes(fields: DataFieldList, sortedField
output += "]"; // 结束数组
return output;
}
+
+
+function toISOString(date) {
+ // 获取日期部分
+ const year = date.getFullYear();
+ const month = String(date.getMonth() + 1).padStart(2, '0'); // 月份是从0开始的
+ const day = String(date.getDate()).padStart(2, '0');
+
+ // 获取时间部分
+ const hours = String(date.getHours()).padStart(2, '0');
+ const minutes = String(date.getMinutes()).padStart(2, '0');
+ const seconds = String(date.getSeconds()).padStart(2, '0');
+
+ // 拼接成 YYYY-MM-DDTHH:mm:ss 格式
+ return `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`;
+}
\ No newline at end of file
diff --git a/src/utils/typeUtils.ts b/src/utils/typeUtils.ts
index b6f247c..1c50988 100644
--- a/src/utils/typeUtils.ts
+++ b/src/utils/typeUtils.ts
@@ -13,4 +13,19 @@ export const calculateByteSize = (str: string) => {
// check variable has value
export function hasValue(variable: any): boolean {
return variable !== null && variable !== undefined;
+}
+
+export function toDateString(date: Date): string {
+ const day = date.getDate().toString().padStart(2, '0');
+ const month = (date.getMonth() + 1).toString().padStart(2, '0');
+ const year = date.getFullYear();
+ return `${day}-${month}-${year}`;
+}
+
+export function toDateTimeString(date: Date): string {
+ const formattedDate = toDateString(date); // Reuse formatDate function
+ const hours = date.getHours().toString().padStart(2, '0');
+ const minutes = date.getMinutes().toString().padStart(2, '0');
+ const seconds = date.getSeconds().toString().padStart(2, '0');
+ return `${formattedDate} ${hours}:${minutes}:${seconds}`;
}
\ No newline at end of file