Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
115 changes: 115 additions & 0 deletions components/seo/TimestampConverterSEO.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,115 @@
import CodeExample from "../CodeExample";

export default function TimestampConverterSEO() {
return (
<div className="content-wrapper">
<section>
<p>
Effortlessly convert timestamps between different timezones with this
free online tool. Whether you&apos;re coordinating events across
regions, analyzing logs, or building global applications, our
timestamp timezone converter makes it easy to translate any date and
time from one timezone to another.
</p>
</section>

<section>
<h2>Key Features:</h2>
<ul>
<li>
<b>Timezone-to-Timezone Conversion:</b> <br /> Instantly convert a
timestamp from any source timezone to your desired target timezone.
</li>
<li>
<b>Supports All Timezones:</b> <br /> Choose from a comprehensive
list of global timezones, including UTC, PST, EST, IST, and more.
</li>
<li>
<b>Handles Daylight Saving:</b> <br /> Automatically adjusts for
daylight saving time changes where applicable.
</li>
<li>
<b>Open Source:</b> <br /> Built by the Jam team and available for
everyone.
</li>
</ul>
</section>

<section>
<h2>How to Use the Timestamp Timezone Converter:</h2>
<p>Converting a timestamp between timezones is simple:</p>
<ul>
<li>
<b>Step 1:</b> <br /> Enter your original timestamp and select its
timezone.
</li>
<li>
<b>Step 2:</b> <br /> Choose the target timezone you want to convert
to.
</li>
<li>
<b>Step 3:</b> <br /> Instantly view the converted date and time in
the target timezone.
</li>
</ul>
<p>
Your timestamp is now accurately converted and ready to use or share
across different regions.
</p>
</section>

<section>
<h2>Why Convert Timestamps Between Timezones?</h2>
<p>
Timezone conversion is essential for global teams, distributed
systems, and anyone working with international data. Converting
timestamps ensures accurate scheduling, reporting, and analysis
regardless of where your users or systems are located.
</p>
</section>

<section>
<h2>How to Convert Timestamps Between Timezones in Code:</h2>
<p>
Need to perform timezone conversions in your own JavaScript or
TypeScript projects? Here&apos;s a sample using <code>luxon</code>:
</p>
</section>

<section>
<CodeExample>{jsCodeExample}</CodeExample>
</section>

<section>
<h2>FAQs:</h2>
<ul>
<li>
<b>Does this tool support all timezones?</b> <br /> Yes, you can
convert between any IANA timezone identifiers.
</li>
<li>
<b>Does it handle daylight saving time?</b> <br /> The converter
automatically adjusts for daylight saving changes.
</li>
<li>
<b>Who can use this converter?</b> <br /> Anyone—developers,
analysts, or anyone working with time data across regions.
</li>
</ul>
</section>
</div>
);
}

const jsCodeExample = `import { DateTime } from "luxon";

function convertTimezone(timestamp: string, fromZone: string, toZone: string) {
// Parse timestamp as ISO string or epoch milliseconds
const dt = DateTime.fromMillis(Number(timestamp), { zone: fromZone });
if (!dt.isValid) throw new Error("Invalid timestamp or timezone");
return dt.setZone(toZone).toFormat("yyyy-LL-dd HH:mm:ss ZZZZ");
}

// Example:
// convertTimezone("1680307200000", "UTC", "America/New_York");
`;
6 changes: 6 additions & 0 deletions components/utils/tools-list.ts
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,12 @@ export const tools = [
"Resize images while maintaining aspect ratio and choose between PNG and JPEG formats with our free tool.",
link: "/utilities/image-resizer",
},
{
title: "Timezone Converter",
description:
"Convert timestamps between different timezones with ease. Perfect for scheduling events across regions and analyzing logs.",
link: "/utilities/timezone-converter",
},
{
title: "JWT Parser",
description:
Expand Down
148 changes: 148 additions & 0 deletions pages/utilities/timezone-converter.test.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
import React from "react";
import { render, fireEvent } from "@testing-library/react";
import TimezoneComparer from "./timezone-converter";

function convertTime(inputTime: string, fromTz: string, toTz: string): string {
if (!inputTime) return "";
const match = inputTime.match(/^(\d{4}):(\d{2}):(\d{2}) (\d{2}):(\d{2})$/);
if (!match) return "Invalid time format";
const [, yearStr, monthStr, dayStr, hourStr, minuteStr] = match;
const year = Number(yearStr);
const month = Number(monthStr);
const day = Number(dayStr);
const hours = Number(hourStr);
const minutes = Number(minuteStr);
if (
isNaN(year) ||
isNaN(month) ||
isNaN(day) ||
isNaN(hours) ||
isNaN(minutes) ||
month < 1 ||
month > 12 ||
day < 1 ||
day > 31 ||
hours < 0 ||
hours > 23 ||
minutes < 0 ||
minutes > 59
)
return "Invalid time format";

let date: Date;
if (fromTz === "UTC") {
date = new Date(Date.UTC(year, month - 1, day, hours, minutes, 0));
} else {
const inputIso = `${yearStr}-${monthStr}-${dayStr}T${hourStr}:${minuteStr}:00`;
const utcMillis = Date.parse(
new Date(
new Intl.DateTimeFormat("en-US", {
timeZone: fromTz,
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
hour12: false,
})
.formatToParts(new Date(inputIso))
.map((p) => p.value)
.join("")
).toISOString()
);
date = new Date(utcMillis);
}

const formatter = new Intl.DateTimeFormat("en-US", {
year: "numeric",
month: "2-digit",
day: "2-digit",
hour: "2-digit",
minute: "2-digit",
hour12: false,
timeZone: toTz,
});
const parts = formatter.formatToParts(date);
const yearPart = parts.find((p) => p.type === "year");
const monthPart = parts.find((p) => p.type === "month");
const dayPart = parts.find((p) => p.type === "day");
const hourPart = parts.find((p) => p.type === "hour");
const minutePart = parts.find((p) => p.type === "minute");
if (!yearPart || !monthPart || !dayPart || !hourPart || !minutePart)
return "Conversion error";
let hourOut = hourPart.value;
if (hourOut === "24") hourOut = "00";
return `${yearPart.value}:${monthPart.value}:${dayPart.value} ${hourOut}:${minutePart.value}`;
}

describe("convertTime", () => {
test("UTC to UTC, same time and date", () => {
expect(convertTime("2024:06:01 12:00", "UTC", "UTC")).toBe(
"2024:06:01 12:00"
);
});

test("UTC to New York, date and time format", () => {
const nyTime = convertTime("2024:06:01 12:00", "UTC", "America/New_York");
expect(/^\d{4}:\d{2}:\d{2} \d{2}:\d{2}$/.test(nyTime)).toBe(true);
});

test("New York to Tokyo, date and time format", () => {
const tokyoTime = convertTime(
"2024:06:01 08:00",
"America/New_York",
"Asia/Tokyo"
);
expect(/^\d{4}:\d{2}:\d{2} \d{2}:\d{2}$/.test(tokyoTime)).toBe(true);
});

test("Invalid hour", () => {
expect(convertTime("2024:06:01 25:00", "UTC", "UTC")).toBe(
"Invalid time format"
);
});

test("Invalid minute", () => {
expect(convertTime("2024:06:01 12:60", "UTC", "UTC")).toBe(
"Invalid time format"
);
});

test("Invalid date", () => {
expect(convertTime("2024:13:01 12:00", "UTC", "UTC")).toBe(
"Invalid time format"
);
expect(convertTime("2024:06:32 12:00", "UTC", "UTC")).toBe(
"Invalid time format"
);
});

test("Empty input", () => {
expect(convertTime("", "UTC", "UTC")).toBe("");
});

test("UTC midnight to Tokyo, date and time format", () => {
const tokyoTime = convertTime("2024:06:01 00:00", "UTC", "Asia/Tokyo");
expect(/^\d{4}:\d{2}:\d{2} \d{2}:\d{2}$/.test(tokyoTime)).toBe(true);
});

test("Handles leap year", () => {
expect(convertTime("2024:02:29 12:00", "UTC", "UTC")).toBe(
"2024:02:29 12:00"
);
});

test("Handles single digit months and days", () => {
expect(convertTime("2024:01:09 09:05", "UTC", "UTC")).toBe(
"2024:01:09 09:05"
);
});

test("Invalid format", () => {
expect(convertTime("2024-06-01 12:00", "UTC", "UTC")).toBe(
"Invalid time format"
);
expect(convertTime("12:00", "UTC", "UTC")).toBe("Invalid time format");
});
});
Loading
Loading