All files / utils date.ts

71.87% Statements 46/64
64% Branches 32/50
66.66% Functions 4/6
77.19% Lines 44/57

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 10911x   11x   45x 45x 45x 45x           11x   8x 8x 8x 8x 8x 8x 8x 8x 8x 8x                 11x             11x           23x 172x   172x 172x 172x 172x   172x       172x   172x               172x             80x 80x   78x 7x 7x 7x     71x 71x   71x       71x 58x     13x 13x   13x 13x                  
import { THREAD_TIMESTAMP_FORMAT, THREAD_TIMESTAMP_LOCALE } from "@/constants/date-time";
 
const ISO_DATE_ONLY_REGEX = /^\d{4}-\d{2}-\d{2}$/;
 
export function formatTimestamp(value: string): string {
  Iif (!value) return "";
  try {
    return new Intl.DateTimeFormat(THREAD_TIMESTAMP_LOCALE, THREAD_TIMESTAMP_FORMAT).format(new Date(value));
  } catch {
    return value;
  }
}
 
const DATE_GROUP_LABELS = ["Today", "Yesterday", "Previous 7 Days", "Previous 30 Days"];
 
export function getThreadDateGroup(updatedAt: string): string {
  const date = new Date(updatedAt);
  const now = new Date();
  const todayStart = new Date(now.getFullYear(), now.getMonth(), now.getDate());
  const dateStart = new Date(date.getFullYear(), date.getMonth(), date.getDate());
  const diffDays = Math.round((todayStart.getTime() - dateStart.getTime()) / (1000 * 60 * 60 * 24));
  Iif (diffDays === 0) return "Today";
  Iif (diffDays === 1) return "Yesterday";
  Iif (diffDays <= 7) return "Previous 7 Days";
  Eif (diffDays <= 30) return "Previous 30 Days";
  return date.toLocaleString("default", { month: "long", year: "numeric" });
}
 
export function getThreadDateGroupOrder(label: string): number {
  const idx = DATE_GROUP_LABELS.indexOf(label);
  return idx === -1 ? DATE_GROUP_LABELS.length : idx;
}
 
const DATE_WITH_YEAR_FORMATTER = new Intl.DateTimeFormat("en-US", {
  month: "short",
  day: "numeric",
  year: "numeric",
  timeZone: "UTC",
});
 
const MONTH_DAY_FORMATTER = new Intl.DateTimeFormat("en-US", {
  month: "short",
  day: "numeric",
  timeZone: "UTC",
});
 
export function parseIsoDateUtc(value: string): Date | null {
  Iif (!ISO_DATE_ONLY_REGEX.test(value)) return null;
 
  const [yearText, monthText, dayText] = value.split("-");
  const year = Number(yearText);
  const month = Number(monthText);
  const day = Number(dayText);
 
  Iif (!Number.isInteger(year) || !Number.isInteger(month) || !Number.isInteger(day)) {
    return null;
  }
 
  const parsed = new Date(Date.UTC(year, month - 1, day));
 
  Iif (
    parsed.getUTCFullYear() !== year ||
    parsed.getUTCMonth() !== month - 1 ||
    parsed.getUTCDate() !== day
  ) {
    return null;
  }
 
  return parsed;
}
 
export function formatDateWithYear(date: Date): string {
  return DATE_WITH_YEAR_FORMATTER.format(date);
}
 
export function formatHumanDateRange(startDate: string, endDate: string): string {
  if (!startDate && !endDate) return "—";
 
  if (!startDate || !endDate) {
    const single = startDate || endDate;
    const parsed = parseIsoDateUtc(single);
    return parsed ? DATE_WITH_YEAR_FORMATTER.format(parsed) : single;
  }
 
  const parsedStart = parseIsoDateUtc(startDate);
  const parsedEnd = parseIsoDateUtc(endDate);
 
  Iif (!parsedStart || !parsedEnd) {
    return startDate === endDate ? startDate : `${startDate} → ${endDate}`;
  }
 
  if (startDate === endDate) {
    return DATE_WITH_YEAR_FORMATTER.format(parsedStart);
  }
 
  const sameYear = parsedStart.getUTCFullYear() === parsedEnd.getUTCFullYear();
  const sameMonth = sameYear && parsedStart.getUTCMonth() === parsedEnd.getUTCMonth();
 
  Eif (sameMonth) {
    return `${MONTH_DAY_FORMATTER.format(parsedStart)}–${parsedEnd.getUTCDate()}, ${parsedStart.getUTCFullYear()}`;
  }
 
  if (sameYear) {
    return `${MONTH_DAY_FORMATTER.format(parsedStart)} – ${MONTH_DAY_FORMATTER.format(parsedEnd)}, ${parsedStart.getUTCFullYear()}`;
  }
 
  return `${DATE_WITH_YEAR_FORMATTER.format(parsedStart)} – ${DATE_WITH_YEAR_FORMATTER.format(parsedEnd)}`;
}