# All files / src/utils time.ts

68.18% Statements 30/44
23.52% Branches 4/17
100% Functions 2/2
68.18% Lines 30/44

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

    174x
    174x
    174x
    174x
    174x
    174x
    174x

    174x

    174x
    6x

    168x
    5x

    163x

    163x

    163x
    163x
    163x
    163x

    14x
    14x

    14x
    14x

    14x

    14x
    14x
    14x
    14x

    14x

    14x
    14x

     /**
     * Formats an ISO timestamp string as a human-readable relative time.
     *
     * Examples:
     *   "just now"   (< 1 minute ago)
     *   "5m ago"     (< 1 hour ago)
     *   "2h ago"     (< 24 hours ago)
     *   "yesterday"  (1–2 days ago)
     *   "3 days ago" (2–7 days ago)
     *   "Feb 27"     (> 7 days ago, same year)
     *   "Feb 27 2025" (different year)
     */
    export function formatRelativeTime(isoString: string): string {
      const date = new Date(isoString);
      const now = new Date();
      const diffMs = now.getTime() - date.getTime();
      const diffSeconds = Math.floor(diffMs / 1000);
      const diffMinutes = Math.floor(diffSeconds / 60);
      const diffHours = Math.floor(diffMinutes / 60);
      const diffDays = Math.floor(diffHours / 24);

      Iif (diffSeconds < 60) {
        return "just now";
      }
      if (diffMinutes < 60) {
        return `${diffMinutes}m ago`;
      }
      if (diffHours < 24) {
        return `${diffHours}h ago`;
      }
      Iif (diffDays === 1) {
        return "yesterday";
      }
      Iif (diffDays < 7) {
        return `${diffDays} days ago`;
      }

      // Older than a week — show a short date
      const sameYear = date.getFullYear() === now.getFullYear();
      const month = date.toLocaleString("en-US", { month: "short" });
      const day = date.getDate();
      return sameYear ? `${month} ${day}` : `${month} ${day} ${date.getFullYear()}`;
    }

    /**
     * Formats an ISO timestamp string as a human-readable countdown to a future event.
     *
     * Examples:
     *   "in 45s"     (< 1 minute away)
     *   "in 5m"      (< 1 hour away)
     *   "in 2h"      (< 24 hours away)
     *   "in 3 days"  (< 7 days away)
     *   "Feb 27"     (> 7 days away, same year)
     *
     * Returns "overdue" if the timestamp is in the past.
     */
    export function formatCountdown(isoString: string): string {
      const date = new Date(isoString);
      Iif (Number.isNaN(date.getTime())) {
        return "\u2014";
      }
      const now = new Date();
      const diffMs = date.getTime() - now.getTime();

      Iif (diffMs <= 0) {
        return "overdue";
      }

      const diffSeconds = Math.floor(diffMs / 1000);
      const diffMinutes = Math.floor(diffSeconds / 60);
      const diffHours = Math.floor(diffMinutes / 60);
      const diffDays = Math.floor(diffHours / 24);

      Iif (diffSeconds < 60) {
        return `in ${diffSeconds}s`;
      }
      if (diffMinutes < 60) {
        return `in ${diffMinutes}m`;
      }
      Iif (diffHours < 24) {
        return `in ${diffHours}h`;
      }
      Iif (diffDays < 7) {
        return `in ${diffDays} day${diffDays === 1 ? "" : "s"}`;
      }

      // Further out — show a short date
      const sameYear = date.getFullYear() === now.getFullYear();
      const month = date.toLocaleString("en-US", { month: "short" });
      const day = date.getDate();
      return sameYear ? `${month} ${day}` : `${month} ${day} ${date.getFullYear()}`;
    }