Add Datatime conversion

This commit is contained in:
chark1es 2025-02-10 22:36:58 -08:00
parent cb549b9b7c
commit b37d7c577c
2 changed files with 106 additions and 22 deletions

View file

@ -12,6 +12,30 @@ interface RequestOptions {
disableAutoCancellation?: boolean; disableAutoCancellation?: boolean;
} }
// Utility function to check if a value is a UTC date string
function isUTCDateString(value: any): boolean {
if (typeof value !== "string") return false;
const isoDateRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}(\.\d{1,3})?Z$/;
return isoDateRegex.test(value);
}
// Utility function to convert UTC date strings to local time
function convertUTCToLocal<T>(data: T): T {
if (!data || typeof data !== "object") return data;
const converted = { ...data };
for (const [key, value] of Object.entries(converted)) {
if (isUTCDateString(value)) {
(converted as any)[key] = new Date(value).toISOString();
} else if (Array.isArray(value)) {
(converted as any)[key] = value.map((item) => convertUTCToLocal(item));
} else if (typeof value === "object" && value !== null) {
(converted as any)[key] = convertUTCToLocal(value);
}
}
return converted;
}
export class Get { export class Get {
private auth: Authentication; private auth: Authentication;
private static instance: Get; private static instance: Get;
@ -30,6 +54,24 @@ export class Get {
return Get.instance; return Get.instance;
} }
/**
* Convert UTC date strings to local time
* @param data The data to convert
* @returns The converted data
*/
public static convertUTCToLocal<T>(data: T): T {
return convertUTCToLocal(data);
}
/**
* Check if a value is a UTC date string
* @param value The value to check
* @returns True if the value is a UTC date string
*/
public static isUTCDateString(value: any): boolean {
return isUTCDateString(value);
}
/** /**
* Get a single record by ID * Get a single record by ID
* @param collectionName The name of the collection * @param collectionName The name of the collection
@ -52,9 +94,10 @@ export class Get {
...(options?.fields && { fields: options.fields.join(",") }), ...(options?.fields && { fields: options.fields.join(",") }),
...(options?.disableAutoCancellation && { requestKey: null }), ...(options?.disableAutoCancellation && { requestKey: null }),
}; };
return await pb const result = await pb
.collection(collectionName) .collection(collectionName)
.getOne<T>(recordId, requestOptions); .getOne<T>(recordId, requestOptions);
return convertUTCToLocal(result);
} catch (err) { } catch (err) {
console.error(`Failed to get record from ${collectionName}:`, err); console.error(`Failed to get record from ${collectionName}:`, err);
throw err; throw err;
@ -90,8 +133,10 @@ export class Get {
.collection(collectionName) .collection(collectionName)
.getFullList<T>(requestOptions); .getFullList<T>(requestOptions);
// Sort results to match the order of requested IDs // Sort results to match the order of requested IDs and convert times
const recordMap = new Map(result.map((record) => [record.id, record])); const recordMap = new Map(
result.map((record) => [record.id, convertUTCToLocal(record)]),
);
return recordIds.map((id) => recordMap.get(id)).filter(Boolean) as T[]; return recordIds.map((id) => recordMap.get(id)).filter(Boolean) as T[];
} catch (err) { } catch (err) {
console.error(`Failed to get records from ${collectionName}:`, err); console.error(`Failed to get records from ${collectionName}:`, err);
@ -145,7 +190,7 @@ export class Get {
perPage: result.perPage, perPage: result.perPage,
totalItems: result.totalItems, totalItems: result.totalItems,
totalPages: result.totalPages, totalPages: result.totalPages,
items: result.items, items: result.items.map((item) => convertUTCToLocal(item)),
}; };
} catch (err) { } catch (err) {
console.error(`Failed to get list from ${collectionName}:`, err); console.error(`Failed to get list from ${collectionName}:`, err);
@ -180,7 +225,10 @@ export class Get {
...(options?.disableAutoCancellation && { requestKey: null }), ...(options?.disableAutoCancellation && { requestKey: null }),
}; };
return await pb.collection(collectionName).getFullList<T>(requestOptions); const result = await pb
.collection(collectionName)
.getFullList<T>(requestOptions);
return result.map((item) => convertUTCToLocal(item));
} catch (err) { } catch (err) {
console.error(`Failed to get all records from ${collectionName}:`, err); console.error(`Failed to get all records from ${collectionName}:`, err);
throw err; throw err;
@ -216,7 +264,9 @@ export class Get {
const result = await pb const result = await pb
.collection(collectionName) .collection(collectionName)
.getList<T>(1, 1, requestOptions); .getList<T>(1, 1, requestOptions);
return result.items.length > 0 ? result.items[0] : null; return result.items.length > 0
? convertUTCToLocal(result.items[0])
: null;
} catch (err) { } catch (err) {
console.error(`Failed to get first record from ${collectionName}:`, err); console.error(`Failed to get first record from ${collectionName}:`, err);
throw err; throw err;

View file

@ -1,5 +1,29 @@
import { Authentication } from "./Authentication"; import { Authentication } from "./Authentication";
// Utility function to check if a value is a date string
function isLocalDateString(value: any): boolean {
if (typeof value !== "string") return false;
const isoDateRegex = /^\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}/;
return isoDateRegex.test(value);
}
// Utility function to convert local time to UTC
function convertLocalToUTC<T>(data: T): T {
if (!data || typeof data !== "object") return data;
const converted = { ...data };
for (const [key, value] of Object.entries(converted)) {
if (isLocalDateString(value)) {
(converted as any)[key] = new Date(value).toISOString();
} else if (Array.isArray(value)) {
(converted as any)[key] = value.map((item) => convertLocalToUTC(item));
} else if (typeof value === "object" && value !== null) {
(converted as any)[key] = convertLocalToUTC(value);
}
}
return converted;
}
export class Update { export class Update {
private auth: Authentication; private auth: Authentication;
private static instance: Update; private static instance: Update;
@ -30,7 +54,7 @@ export class Update {
collectionName: string, collectionName: string,
recordId: string, recordId: string,
field: string, field: string,
value: any value: any,
): Promise<T> { ): Promise<T> {
if (!this.auth.isAuthenticated()) { if (!this.auth.isAuthenticated()) {
throw new Error("User must be authenticated to update records"); throw new Error("User must be authenticated to update records");
@ -40,7 +64,10 @@ export class Update {
this.auth.setUpdating(true); this.auth.setUpdating(true);
const pb = this.auth.getPocketBase(); const pb = this.auth.getPocketBase();
const data = { [field]: value }; const data = { [field]: value };
const result = await pb.collection(collectionName).update<T>(recordId, data); const convertedData = convertLocalToUTC(data);
const result = await pb
.collection(collectionName)
.update<T>(recordId, convertedData);
return result; return result;
} catch (err) { } catch (err) {
console.error(`Failed to update ${field} in ${collectionName}:`, err); console.error(`Failed to update ${field} in ${collectionName}:`, err);
@ -60,7 +87,7 @@ export class Update {
public async updateFields<T = any>( public async updateFields<T = any>(
collectionName: string, collectionName: string,
recordId: string, recordId: string,
updates: Record<string, any> updates: Record<string, any>,
): Promise<T> { ): Promise<T> {
if (!this.auth.isAuthenticated()) { if (!this.auth.isAuthenticated()) {
throw new Error("User must be authenticated to update records"); throw new Error("User must be authenticated to update records");
@ -69,7 +96,10 @@ export class Update {
try { try {
this.auth.setUpdating(true); this.auth.setUpdating(true);
const pb = this.auth.getPocketBase(); const pb = this.auth.getPocketBase();
const result = await pb.collection(collectionName).update<T>(recordId, updates); const convertedUpdates = convertLocalToUTC(updates);
const result = await pb
.collection(collectionName)
.update<T>(recordId, convertedUpdates);
return result; return result;
} catch (err) { } catch (err) {
console.error(`Failed to update fields in ${collectionName}:`, err); console.error(`Failed to update fields in ${collectionName}:`, err);
@ -91,7 +121,7 @@ export class Update {
collectionName: string, collectionName: string,
recordIds: string[], recordIds: string[],
field: string, field: string,
value: any value: any,
): Promise<T[]> { ): Promise<T[]> {
if (!this.auth.isAuthenticated()) { if (!this.auth.isAuthenticated()) {
throw new Error("User must be authenticated to update records"); throw new Error("User must be authenticated to update records");
@ -101,15 +131,19 @@ export class Update {
this.auth.setUpdating(true); this.auth.setUpdating(true);
const pb = this.auth.getPocketBase(); const pb = this.auth.getPocketBase();
const data = { [field]: value }; const data = { [field]: value };
const convertedData = convertLocalToUTC(data);
const updates = recordIds.map(id =>
pb.collection(collectionName).update<T>(id, data) const updates = recordIds.map((id) =>
pb.collection(collectionName).update<T>(id, convertedData),
); );
const results = await Promise.all(updates); const results = await Promise.all(updates);
return results; return results;
} catch (err) { } catch (err) {
console.error(`Failed to batch update ${field} in ${collectionName}:`, err); console.error(
`Failed to batch update ${field} in ${collectionName}:`,
err,
);
throw err; throw err;
} finally { } finally {
this.auth.setUpdating(false); this.auth.setUpdating(false);
@ -124,7 +158,7 @@ export class Update {
*/ */
public async batchUpdateFields<T = any>( public async batchUpdateFields<T = any>(
collectionName: string, collectionName: string,
updates: Array<{ id: string; data: Record<string, any> }> updates: Array<{ id: string; data: Record<string, any> }>,
): Promise<T[]> { ): Promise<T[]> {
if (!this.auth.isAuthenticated()) { if (!this.auth.isAuthenticated()) {
throw new Error("User must be authenticated to update records"); throw new Error("User must be authenticated to update records");
@ -133,11 +167,11 @@ export class Update {
try { try {
this.auth.setUpdating(true); this.auth.setUpdating(true);
const pb = this.auth.getPocketBase(); const pb = this.auth.getPocketBase();
const updatePromises = updates.map(({ id, data }) => const updatePromises = updates.map(({ id, data }) =>
pb.collection(collectionName).update<T>(id, data) pb.collection(collectionName).update<T>(id, convertLocalToUTC(data)),
); );
const results = await Promise.all(updatePromises); const results = await Promise.all(updatePromises);
return results; return results;
} catch (err) { } catch (err) {
@ -147,4 +181,4 @@ export class Update {
this.auth.setUpdating(false); this.auth.setUpdating(false);
} }
} }
} }