feat: enhance date handling and formatting in quotes and belo features
This commit is contained in:
@@ -8,3 +8,13 @@ export function startOfToday(): Date {
|
|||||||
d.setHours(0, 0, 0, 0);
|
d.setHours(0, 0, 0, 0);
|
||||||
return d;
|
return d;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function parseLocalDate(dateStr: string): Date {
|
||||||
|
const [y, m, d] = dateStr.split("-").map(Number);
|
||||||
|
return new Date(y, m - 1, d);
|
||||||
|
}
|
||||||
|
|
||||||
|
export function startOfNextLocalDay(dateStr: string): Date {
|
||||||
|
const [y, m, d] = dateStr.split("-").map(Number);
|
||||||
|
return new Date(y, m - 1, d + 1);
|
||||||
|
}
|
||||||
|
|||||||
@@ -25,7 +25,9 @@ export const payExpenseSchema = z.object({
|
|||||||
|
|
||||||
export const updateExpenseSchema = z.object({
|
export const updateExpenseSchema = z.object({
|
||||||
amount: z.number().positive("El monto debe ser mayor a 0"),
|
amount: z.number().positive("El monto debe ser mayor a 0"),
|
||||||
dueDate: z.string().datetime({ message: "La fecha debe ser una fecha ISO válida" }),
|
dueDate: z
|
||||||
|
.string()
|
||||||
|
.datetime({ message: "La fecha debe ser una fecha ISO válida" }),
|
||||||
});
|
});
|
||||||
|
|
||||||
function lastDayOfMonth(year: number, month: number): number {
|
function lastDayOfMonth(year: number, month: number): number {
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { Context } from "hono";
|
|||||||
import type { QuoteType } from "../../../generated/prisma/client";
|
import type { QuoteType } from "../../../generated/prisma/client";
|
||||||
import { cache } from "../../../lib/cache";
|
import { cache } from "../../../lib/cache";
|
||||||
import { prisma } from "../../../lib/prisma";
|
import { prisma } from "../../../lib/prisma";
|
||||||
|
import { parseLocalDate, startOfNextLocalDay } from "../../../lib/utils";
|
||||||
|
|
||||||
const VALID_TYPES = ["BLUE", "BNA", "BELO"] as const;
|
const VALID_TYPES = ["BLUE", "BNA", "BELO"] as const;
|
||||||
|
|
||||||
@@ -22,11 +23,9 @@ export async function getDailyMinMax(c: Context) {
|
|||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const startDate = startDateParam
|
const startDate = startDateParam
|
||||||
? new Date(startDateParam)
|
? parseLocalDate(startDateParam)
|
||||||
: new Date(now.getFullYear(), now.getMonth(), 1);
|
: new Date(now.getFullYear(), now.getMonth(), 1);
|
||||||
const endDate = endDateParam
|
const endDate = endDateParam ? startOfNextLocalDay(endDateParam) : now;
|
||||||
? new Date(new Date(endDateParam).getTime() + 86_400_000)
|
|
||||||
: now;
|
|
||||||
|
|
||||||
if (Number.isNaN(startDate.getTime()) || Number.isNaN(endDate.getTime())) {
|
if (Number.isNaN(startDate.getTime()) || Number.isNaN(endDate.getTime())) {
|
||||||
return c.json({ error: "Invalid date format. Use ISO 8601." }, 400);
|
return c.json({ error: "Invalid date format. Use ISO 8601." }, 400);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { Context } from "hono";
|
import type { Context } from "hono";
|
||||||
import { cache } from "../../../lib/cache";
|
import { cache } from "../../../lib/cache";
|
||||||
import { prisma } from "../../../lib/prisma";
|
import { prisma } from "../../../lib/prisma";
|
||||||
|
import { parseLocalDate, startOfNextLocalDay } from "../../../lib/utils";
|
||||||
|
|
||||||
const VALID_TYPES = ["BLUE", "BNA", "BELO"] as const;
|
const VALID_TYPES = ["BLUE", "BNA", "BELO"] as const;
|
||||||
|
|
||||||
@@ -21,11 +22,9 @@ export async function getDailyQuotes(c: Context) {
|
|||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const startDate = startDateParam
|
const startDate = startDateParam
|
||||||
? new Date(startDateParam)
|
? parseLocalDate(startDateParam)
|
||||||
: new Date(now.getFullYear(), now.getMonth(), 1);
|
: new Date(now.getFullYear(), now.getMonth(), 1);
|
||||||
const endDate = endDateParam
|
const endDate = endDateParam ? startOfNextLocalDay(endDateParam) : now;
|
||||||
? new Date(new Date(endDateParam).getTime() + 86_400_000)
|
|
||||||
: now;
|
|
||||||
|
|
||||||
if (Number.isNaN(startDate.getTime()) || Number.isNaN(endDate.getTime())) {
|
if (Number.isNaN(startDate.getTime()) || Number.isNaN(endDate.getTime())) {
|
||||||
return c.json({ error: "Invalid date format. Use ISO 8601." }, 400);
|
return c.json({ error: "Invalid date format. Use ISO 8601." }, 400);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import type { Context } from "hono";
|
|||||||
import type { QuoteType } from "../../../generated/prisma/client";
|
import type { QuoteType } from "../../../generated/prisma/client";
|
||||||
import { cache } from "../../../lib/cache";
|
import { cache } from "../../../lib/cache";
|
||||||
import { prisma } from "../../../lib/prisma";
|
import { prisma } from "../../../lib/prisma";
|
||||||
|
import { parseLocalDate, startOfNextLocalDay } from "../../../lib/utils";
|
||||||
|
|
||||||
const VALID_TYPES = ["BLUE", "BNA", "BELO"] as const;
|
const VALID_TYPES = ["BLUE", "BNA", "BELO"] as const;
|
||||||
|
|
||||||
@@ -23,11 +24,9 @@ export async function getQuoteHistory(c: Context) {
|
|||||||
|
|
||||||
const now = new Date();
|
const now = new Date();
|
||||||
const startDate = startDateParam
|
const startDate = startDateParam
|
||||||
? new Date(startDateParam)
|
? parseLocalDate(startDateParam)
|
||||||
: new Date(now.getFullYear(), now.getMonth(), 1);
|
: new Date(now.getFullYear(), now.getMonth(), 1);
|
||||||
const endDate = endDateParam
|
const endDate = endDateParam ? startOfNextLocalDay(endDateParam) : now;
|
||||||
? new Date(new Date(endDateParam).getTime() + 86_400_000)
|
|
||||||
: now;
|
|
||||||
|
|
||||||
if (Number.isNaN(startDate.getTime()) || Number.isNaN(endDate.getTime())) {
|
if (Number.isNaN(startDate.getTime()) || Number.isNaN(endDate.getTime())) {
|
||||||
return c.json({ error: "Invalid date format. Use ISO 8601." }, 400);
|
return c.json({ error: "Invalid date format. Use ISO 8601." }, 400);
|
||||||
|
|||||||
@@ -28,11 +28,8 @@ function formatDate(d: Date): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function formatShortDate(iso: string): string {
|
function formatShortDate(iso: string): string {
|
||||||
const d = new Date(iso);
|
const [, m, d] = iso.split("-");
|
||||||
return d.toLocaleDateString("es-AR", {
|
return `${d}/${m}`;
|
||||||
day: "2-digit",
|
|
||||||
month: "2-digit",
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
export function BeloAnalysisPage() {
|
export function BeloAnalysisPage() {
|
||||||
@@ -315,7 +312,7 @@ export function BeloAnalysisPage() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Line
|
<Line
|
||||||
type="monotone"
|
type="linear"
|
||||||
dataKey="buy"
|
dataKey="buy"
|
||||||
name="Compra"
|
name="Compra"
|
||||||
stroke="var(--chart-1)"
|
stroke="var(--chart-1)"
|
||||||
|
|||||||
@@ -46,11 +46,8 @@ function formatTime(iso: string): string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
function formatShortDate(iso: string): string {
|
function formatShortDate(iso: string): string {
|
||||||
const d = new Date(iso);
|
const [, m, d] = iso.split("-");
|
||||||
return d.toLocaleDateString("es-AR", {
|
return `${d}/${m}`;
|
||||||
day: "2-digit",
|
|
||||||
month: "2-digit",
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
function getGaugeColor(percentage: number | null): string {
|
function getGaugeColor(percentage: number | null): string {
|
||||||
@@ -395,7 +392,7 @@ export function BeloPage() {
|
|||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<Line
|
<Line
|
||||||
type="monotone"
|
type="linear"
|
||||||
dataKey="buy"
|
dataKey="buy"
|
||||||
name="Compra"
|
name="Compra"
|
||||||
stroke="var(--chart-1)"
|
stroke="var(--chart-1)"
|
||||||
@@ -405,7 +402,7 @@ export function BeloPage() {
|
|||||||
isAnimationActive={false}
|
isAnimationActive={false}
|
||||||
/>
|
/>
|
||||||
<Line
|
<Line
|
||||||
type="monotone"
|
type="linear"
|
||||||
dataKey="sell"
|
dataKey="sell"
|
||||||
name="Venta"
|
name="Venta"
|
||||||
stroke="var(--chart-2)"
|
stroke="var(--chart-2)"
|
||||||
|
|||||||
Reference in New Issue
Block a user