mirror of
https://github.com/mayswind/ezbookkeeping.git
synced 2026-05-16 16:07:33 +08:00
import transaction from custom delimiter-separated values file
This commit is contained in:
@@ -230,6 +230,78 @@ export class MeridiemIndicator {
|
||||
}
|
||||
}
|
||||
|
||||
export class KnownDateTimeFormat {
|
||||
private static readonly allInstances: KnownDateTimeFormat[] = [];
|
||||
|
||||
public static readonly DefaultDateTime = new KnownDateTimeFormat('YYYY-MM-DD HH:mm:ss', /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) ([0-1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/);
|
||||
public static readonly DefaultDateTimeWithTimezone = new KnownDateTimeFormat('YYYY-MM-DD HH:mm:ssZ', /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) ([0-1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](Z|[+-](0[0-9]|1[0-4]):[0-5][0-9])$/);
|
||||
public static readonly DefaultDateTimeWithoutSecond = new KnownDateTimeFormat('YYYY-MM-DD HH:mm', /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1]) ([0-1][0-9]|2[0-3]):[0-5][0-9]$/);
|
||||
public static readonly DefaultDate = new KnownDateTimeFormat('YYYY-MM-DD', /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])$/);
|
||||
public static readonly RFC3339 = new KnownDateTimeFormat('YYYY-MM-DDTHH:mm:ssZ', /^\d{4}-(0[1-9]|1[0-2])-(0[1-9]|[1-2][0-9]|3[0-1])T([0-1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9](Z|[+-](0[0-9]|1[0-4]):[0-5][0-9])$/);
|
||||
public static readonly YYYYMMDDSlashWithTime = new KnownDateTimeFormat('YYYY/MM/DD HH:mm:ss', /^\d{4}\/(0[1-9]|1[0-2])\/(0[1-9]|[1-2][0-9]|3[0-1]) ([0-1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/);
|
||||
public static readonly MMDDYYSlashWithTime = new KnownDateTimeFormat('MM/DD/YYYY HH:mm:ss', /^(0[1-9]|1[0-2])\/(0[1-9]|[1-2][0-9]|3[0-1])\/\d{4} ([0-1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/);
|
||||
public static readonly DDMMYYSlashWithTime = new KnownDateTimeFormat('DD/MM/YYYY HH:mm:ss', /^(0[1-9]|[1-2][0-9]|3[0-1])\/(0[1-9]|1[0-2])\/\d{4} ([0-1][0-9]|2[0-3]):[0-5][0-9]:[0-5][0-9]$/);
|
||||
public static readonly YYYYMMDDSlash = new KnownDateTimeFormat('YYYY/MM/DD', /^\d{4}\/(0[1-9]|1[0-2])\/(0[1-9]|[1-2][0-9]|3[0-1])$/);
|
||||
public static readonly MMDDYYSlash = new KnownDateTimeFormat('MM/DD/YYYY', /^(0[1-9]|1[0-2])\/(0[1-9]|[1-2][0-9]|3[0-1])\/\d{4}$/);
|
||||
public static readonly DDMMYYSlash = new KnownDateTimeFormat('DD/MM/YYYY', /^(0[1-9]|[1-2][0-9]|3[0-1])\/(0[1-9]|1[0-2])\/\d{4}$/);
|
||||
|
||||
public readonly format: string;
|
||||
private readonly regex: RegExp;
|
||||
|
||||
private constructor(format: string, regex: RegExp) {
|
||||
this.format = format;
|
||||
this.regex = regex;
|
||||
|
||||
KnownDateTimeFormat.allInstances.push(this);
|
||||
}
|
||||
|
||||
public isValid(dateTime: string): boolean {
|
||||
return this.regex.test(dateTime);
|
||||
}
|
||||
|
||||
public static values(): KnownDateTimeFormat[] {
|
||||
return KnownDateTimeFormat.allInstances;
|
||||
}
|
||||
|
||||
public static detect(dateTime: string): KnownDateTimeFormat[] | undefined {
|
||||
const result: KnownDateTimeFormat[] = [];
|
||||
|
||||
for (const format of KnownDateTimeFormat.allInstances) {
|
||||
if (format.isValid(dateTime)) {
|
||||
result.push(format);
|
||||
}
|
||||
}
|
||||
|
||||
return result.length > 0 ? result : undefined;
|
||||
}
|
||||
|
||||
public static detectMany(dateTimes: string[]): KnownDateTimeFormat[] | undefined {
|
||||
const detectedCounts: Record<string, number> = {};
|
||||
|
||||
for (const dateTime of dateTimes) {
|
||||
const detectedFormats = KnownDateTimeFormat.detect(dateTime);
|
||||
|
||||
if (detectedFormats) {
|
||||
for (const format of detectedFormats) {
|
||||
detectedCounts[format.format] = (detectedCounts[format.format] || 0) + 1;
|
||||
}
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const result: KnownDateTimeFormat[] = [];
|
||||
|
||||
for (const format of KnownDateTimeFormat.allInstances) {
|
||||
if (detectedCounts[format.format] === dateTimes.length) {
|
||||
result.push(format);
|
||||
}
|
||||
}
|
||||
|
||||
return result.length > 0 ? result : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export const LANGUAGE_DEFAULT_DATE_TIME_FORMAT_VALUE: number = 0;
|
||||
|
||||
export interface DateFormat {
|
||||
|
||||
@@ -8,6 +8,8 @@ export interface ImportFileType extends ImportFileTypeAndExtensions {
|
||||
readonly name: string;
|
||||
readonly extensions: string;
|
||||
readonly subTypes?: ImportFileTypeSubType[];
|
||||
readonly supportedEncodings?: string[];
|
||||
readonly dataFromTextbox?: boolean;
|
||||
readonly document?: {
|
||||
readonly supportMultiLanguages: boolean | string;
|
||||
readonly anchor: string;
|
||||
@@ -25,6 +27,8 @@ export interface LocalizedImportFileType extends ImportFileTypeAndExtensions {
|
||||
readonly displayName: string;
|
||||
readonly extensions: string;
|
||||
readonly subTypes?: LocalizedImportFileTypeSubType[];
|
||||
readonly supportedEncodings?: LocalizedImportFileTypeSupportedEncodings[];
|
||||
readonly dataFromTextbox?: boolean;
|
||||
readonly document?: LocalizedImportFileDocument;
|
||||
}
|
||||
|
||||
@@ -34,6 +38,11 @@ export interface LocalizedImportFileTypeSubType extends ImportFileTypeAndExtensi
|
||||
readonly extensions?: string;
|
||||
}
|
||||
|
||||
export interface LocalizedImportFileTypeSupportedEncodings {
|
||||
readonly encoding: string;
|
||||
readonly displayName: string;
|
||||
}
|
||||
|
||||
export interface LocalizedImportFileDocument {
|
||||
readonly language: string;
|
||||
readonly displayLanguageName: string;
|
||||
|
||||
+72
-1
@@ -1,4 +1,4 @@
|
||||
import type { TypeAndName } from './base.ts';
|
||||
import type { NameValue, TypeAndName } from './base.ts';
|
||||
|
||||
export interface TimezoneInfo {
|
||||
readonly displayName: string;
|
||||
@@ -13,6 +13,77 @@ export interface LocalizedTimezoneInfo {
|
||||
readonly displayNameWithUtcOffset: string;
|
||||
}
|
||||
|
||||
export class KnownDateTimezoneFormat implements NameValue {
|
||||
private static readonly allInstances: KnownDateTimezoneFormat[] = [];
|
||||
private static readonly allInstancesByValue: Record<string, KnownDateTimezoneFormat> = {};
|
||||
|
||||
public static readonly HHColonMM = new KnownDateTimezoneFormat('±HH:mm', 'Z', /^[+-]?([0-1][0-9]|2[0-3]):[0-5][0-9]$/);
|
||||
public static readonly HHMM = new KnownDateTimezoneFormat('±HHmm', 'ZZ', /^[+-]?([0-1][0-9]|2[0-3])[0-5][0-9]$/);
|
||||
|
||||
public readonly name: string;
|
||||
public readonly value: string;
|
||||
private readonly regex: RegExp;
|
||||
|
||||
private constructor(name: string, value: string, regex: RegExp) {
|
||||
this.name = name;
|
||||
this.value = value;
|
||||
this.regex = regex;
|
||||
|
||||
KnownDateTimezoneFormat.allInstances.push(this);
|
||||
KnownDateTimezoneFormat.allInstancesByValue[value] = this;
|
||||
}
|
||||
|
||||
public isValid(dateTime: string): boolean {
|
||||
return this.regex.test(dateTime);
|
||||
}
|
||||
|
||||
public static values(): KnownDateTimezoneFormat[] {
|
||||
return KnownDateTimezoneFormat.allInstances;
|
||||
}
|
||||
|
||||
public static valueOf(value: string): KnownDateTimezoneFormat | undefined {
|
||||
return KnownDateTimezoneFormat.allInstancesByValue[value];
|
||||
}
|
||||
|
||||
public static detect(dateTime: string): KnownDateTimezoneFormat[] | undefined {
|
||||
const result: KnownDateTimezoneFormat[] = [];
|
||||
|
||||
for (const format of KnownDateTimezoneFormat.allInstances) {
|
||||
if (format.isValid(dateTime)) {
|
||||
result.push(format);
|
||||
}
|
||||
}
|
||||
|
||||
return result.length > 0 ? result : undefined;
|
||||
}
|
||||
|
||||
public static detectMany(dateTimes: string[]): KnownDateTimezoneFormat[] | undefined {
|
||||
const detectedCounts: Record<string, number> = {};
|
||||
|
||||
for (const dateTime of dateTimes) {
|
||||
const detectedFormats = KnownDateTimezoneFormat.detect(dateTime);
|
||||
|
||||
if (detectedFormats) {
|
||||
for (const format of detectedFormats) {
|
||||
detectedCounts[format.value] = (detectedCounts[format.value] || 0) + 1;
|
||||
}
|
||||
} else {
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
|
||||
const result: KnownDateTimezoneFormat[] = [];
|
||||
|
||||
for (const format of KnownDateTimezoneFormat.allInstances) {
|
||||
if (detectedCounts[format.value] === dateTimes.length) {
|
||||
result.push(format);
|
||||
}
|
||||
}
|
||||
|
||||
return result.length > 0 ? result : undefined;
|
||||
}
|
||||
}
|
||||
|
||||
export class TimezoneTypeForStatistics implements TypeAndName {
|
||||
public static readonly ApplicationTimezone = new TimezoneTypeForStatistics(0, 'Application Timezone');
|
||||
public static readonly TransactionTimezone = new TimezoneTypeForStatistics(1, 'Transaction Timezone');
|
||||
|
||||
@@ -57,3 +57,36 @@ export class TransactionTagFilterType implements TypeAndName {
|
||||
return TransactionTagFilterType.allInstances;
|
||||
}
|
||||
}
|
||||
|
||||
export class ImportTransactionColumnType implements TypeAndName {
|
||||
private static readonly allInstances: ImportTransactionColumnType[] = [];
|
||||
|
||||
public static readonly TransactionTime = new ImportTransactionColumnType(1, 'Transaction Time');
|
||||
public static readonly TransactionTimezone = new ImportTransactionColumnType(2, 'Transaction Timezone');
|
||||
public static readonly TransactionType = new ImportTransactionColumnType(3, 'Transaction Type');
|
||||
public static readonly Category = new ImportTransactionColumnType(4, 'Category');
|
||||
public static readonly SubCategory = new ImportTransactionColumnType(5, 'Secondary Category');
|
||||
public static readonly AccountName = new ImportTransactionColumnType(6, 'Account Name');
|
||||
public static readonly AccountCurrency = new ImportTransactionColumnType(7, 'Currency');
|
||||
public static readonly Amount = new ImportTransactionColumnType(8, 'Amount');
|
||||
public static readonly RelatedAccountName = new ImportTransactionColumnType(9, 'Transfer In Account Name');
|
||||
public static readonly RelatedAccountCurrency = new ImportTransactionColumnType(10, 'Transfer In Currency');
|
||||
public static readonly RelatedAmount = new ImportTransactionColumnType(11, 'Transfer In Amount');
|
||||
public static readonly GeographicLocation = new ImportTransactionColumnType(12, 'Geographic Location');
|
||||
public static readonly Tags = new ImportTransactionColumnType(13, 'Tags');
|
||||
public static readonly Description = new ImportTransactionColumnType(14, 'Description');
|
||||
|
||||
public readonly type: number;
|
||||
public readonly name: string;
|
||||
|
||||
private constructor(type: number, name: string) {
|
||||
this.type = type;
|
||||
this.name = name;
|
||||
|
||||
ImportTransactionColumnType.allInstances.push(this);
|
||||
}
|
||||
|
||||
public static values(): ImportTransactionColumnType[] {
|
||||
return ImportTransactionColumnType.allInstances;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user