Subject: Let build useDateFormatter react custom hook without any libraries only with Native JavaScript.

Have you ever seen a date like this in your app that comes from the backend?

"2024-04-29T07:30:00.000Z"

And wondered why it looks weird, or why it's showing the wrong time?
That’s because dates coming from a backend (like Node.js + PostgreSQL) are usually in ISO format, in UTC time, and not user-friendly.

🚫 The Wrong Way: Using TO_CHAR in PostgreSQL

This is what many people do in their SQL:

SELECT TO_CHAR(emp.emp_join_date, 'DD-MM-YYYY') AS emp_join_date FROM employees;

output:

"29-04-2025"

and thought, “Looks fine, right?”

👎 Nope. That format might look nice, but it breaks a lot of things in your app later.

Let’s understand why it's bad to format dates in PostgreSQL, and then fix it using a clean, reusable React useDateFormatter custom hook.

Here's why it causes real problems:

❌ Disadvantages of TO_CHAR(date, 'DD-MM-YYYY')

Problem Why it’s bad
1. Loses Date Type TO_CHAR turns your date into a plain text string. So the frontend can't sort, compare, or manipulate it like a real Date.
2. Not ISO/Standard 'DD-MM-YYYY' is not a universal format. JS expects ISO like '2025-04-29T00:00:00Z'. Manual parsing is needed.
3. Hard to Re-format Later If frontend wants to show it as April 29, 2025 or local time — you can't. It’s just a string!
4. No Time Info You lose the hours, minutes, seconds — which might matter for logs, tickets, comments, etc.
5. No Timezone Awareness There's no way to tell if the date was in UTC, IST, PST, etc. You risk showing wrong times to users.

✅ The Right Way: Send Raw Dates (as ISO) from Backend

Instead of this:

SELECT TO_CHAR(emp_join_date, 'DD-MM-YYYY') AS emp_join_date FROM employees;

Do this:

SELECT emp_join_date FROM employees;

Let the date stay as a proper timestamp or ISO string ("2025-04-29T00:00:00.000Z"), and then format it in React using a reusable hook.


💡 Solution 1: A fundamental approach.

🔧 The Reusable useDateFormatter React Hook

Let’s build a simple hook in TypeScript that works in any component.

// hooks/useDateFormatter.ts
import { useCallback } from "react";

type FormatOptions = Intl.DateTimeFormatOptions;

const defaultOptions: FormatOptions = {
  year: "numeric",
  month: "short",
  day: "numeric",
  hour: "2-digit",
  minute: "2-digit",
};

export const useDateFormatter = () => {
  const formatDate = useCallback(
    (
      dateInput: string | number | Date | null | undefined,
      options: FormatOptions = defaultOptions
    ): string => {
      if (!dateInput) return "N/A";

      const date = new Date(dateInput);
      if (isNaN(date.getTime())) return "Invalid Date";

      return new Intl.DateTimeFormat(undefined, options).format(date); // locale-aware
    },
    []
  );

  return { formatDate };
};

🧪 Example Usage in a Component

// components/EmployeeCard.tsx
import React from "react";
import { useDateFormatter } from "../hooks/useDateFormatter";

type Employee = {
  name: string;
  emp_join_date: string;
};

const EmployeeCard: React.FC<{ emp: Employee }> = ({ emp }) => {
  const { formatDate } = useDateFormatter();

  return (
    <div>
      <h4>{emp.name}h4>
      <p>Joined on: {formatDate(emp.emp_join_date)}p>
    div>
  );
};

export default EmployeeCard;

⚡ Real-World Use Case

Imagine you're building an HR dashboard. If the date is a string like "29-04-2025", this fails:

const date = new Date("29-04-2025"); // ❌ Invalid Date in many browsers

But if you get a raw ISO date like "2025-04-29T00:00:00Z", it's perfect:

const date = new Date("2025-04-29T00:00:00Z"); // ✅ Works everywhere

Then useDateFormatter formats it for display.


When to Use Just Native Intl.DateTimeFormat (like the above solution1)

✅ Pros:

  • Zero dependencies — no need to install any libraries.
  • Lightweight — perfect for small apps or dashboards.
  • Localized formatting based on user’s browser language.
  • Handles common formatting needs: short/long date, time, etc. Works great for:
  • Showing dates like "Apr 29, 2025, 10:00 AM"
  • Safe fallback behavior for invalid/missing dates

❌ Cons:

  • Limited support for custom formats like "YYYY-MM-DD HH:mm".
  • Hard to manipulate dates (e.g. add/subtract days, set timezones).
  • Browser support for time zones via Intl.DateTimeFormat is decent, but not fully flexible like dayjs.

✅ Now you know how to format dates cleanly using native JavaScript!

But what if you need timezones, custom formats, or date math?

👉 Read Part 2: Building useDateFormatter with dayjs + timezone support