Skip to content

Instantly share code, notes, and snippets.

@wirtaw
Last active December 20, 2025 09:44
Show Gist options
  • Select an option

  • Save wirtaw/c03155ee493e93cf3341892d629e3aa8 to your computer and use it in GitHub Desktop.

Select an option

Save wirtaw/c03155ee493e93cf3341892d629e3aa8 to your computer and use it in GitHub Desktop.
Luxon package use cases

How to Implement and Use

  • Initialize your project: If you haven't already, make sure you have a package.json and install Luxon:
npm init -y
npm install luxon
  • Create the file: Save the code above as explain-date.js.
  • Run the script:
node explain-date.js
/**
* Gist: Biorhythm Milestone Calculator
* Description: Calculates current biorhythm cycles, tomorrow's outlook,
* and identifies upcoming life-day milestones (every 100 and 1000 days).
* Requirements: npm install luxon
*/
import { DateTime } from 'luxon';
/**
* Finds upcoming milestone days (e.g., every 100 or 1000 days)
*/
function takeDates(startDay, divisor) {
const milestones = [];
let current = startDay;
// Look for the next 11 milestones or up to a safety limit
while (current < 42000 || milestones.length < 11) {
if (current % divisor === 0) {
milestones.push(current);
}
current++;
}
return milestones;
}
/**
* Calculates biorhythm value (-1 to 1) for a specific cycle period
*/
function getBiorhythm(daysAlive, period) {
const phase = (daysAlive % period) / period * 2 * Math.PI;
const y = Math.sin(phase);
return y.toFixed(2);
}
/**
* Main Logic
*/
const birthDate = '1985-05-09';
const dtBirth = DateTime.fromISO(birthDate);
const now = DateTime.local();
// Calculate total days alive
const diff = now.diff(dtBirth, 'days');
const lifeDays = Math.floor(diff.days);
console.info(`--- Biorhythm Report ---`);
console.info(`Birth Date: ${dtBirth.toISODate()}`);
console.info(`Days Alive: ${lifeDays}\n`);
// 1. Calculate Milestones
const hundreds = takeDates(lifeDays, 100);
if (hundreds[0]) {
// Use birth date as starting point for addition
const nextMilestoneDate = dtBirth.plus({ days: hundreds[0] });
console.info(`Next 100-day Milestone: ${nextMilestoneDate.toISODate()} (Day ${hundreds[0]})`);
}
// 2. Today's Calculations
const cycles = [
{ name: 'Emotional', period: 28 },
{ name: 'Physical', period: 23 },
{ name: 'Intellectual', period: 33 }
];
console.info(`\n--- Today's Status ---`);
const todayResults = cycles.map(cycle => {
const val = getBiorhythm(lifeDays, cycle.period);
const percent = ((1 + Number(val)) / 2 * 100).toFixed(2);
console.info(`${cycle.name.padEnd(12)}: ${val} (${percent}%)`);
return { ...cycle, today: val };
});
// 3. Tomorrow's Outlook & Changes
console.info(`\n--- Tomorrow's Change ---`);
todayResults.forEach(cycle => {
const tomorrowVal = getBiorhythm(lifeDays + 1, cycle.period);
const change = (Number(tomorrowVal) - Number(cycle.today)).toFixed(2);
const direction = change > 0 ? '↗' : '↘';
console.info(`${cycle.name.padEnd(12)}: ${tomorrowVal} (Change: ${change} ${direction})`);
});
'use strict';
/**
* Gist: Luxon Parsing Debugger
* Purpose: Demonstrates how to use fromFormatExplain to debug date parsing.
* Requirements: npm install luxon
*/
const { DateTime } = require('luxon');
// The input date string containing: Date, Time, Offset (ZZZ), and Zone Name (z)
const DATE_STRING = '2020-11-16 13:21:41 +0200 EET';
// The tokens must match the input string exactly
// yyyy-MM-dd -> 2020-11-16
// HH:mm:ss -> 13:21:41
// ZZZ -> +0200 (Offset)
// z -> EET (Named Zone)
const FORMAT = "yyyy-MM-dd HH:mm:ss ZZZ z";
(() => {
console.info(`--- Execution Started: ${(new Date()).toUTCString()} ---`);
// 1. Explain the parsing process
// This returns an object showing matches, remainders, and validity.
console.log("\n[1] Parsing Explanation:");
const explanation = DateTime.fromFormatExplain(DATE_STRING, FORMAT);
console.dir(explanation, { depth: 3 });
// 2. Create the DateTime object
const dt = DateTime.fromFormat(DATE_STRING, FORMAT);
// 3. Output the result
if (dt.isValid) {
console.log("\n[2] Successfully Parsed DateTime Object:");
console.dir(dt.toObject(), { depth: 1 });
console.log(`ISO String: ${dt.toISOString()}`);
} else {
console.error("\n[!] Parsing Failed:", dt.invalidReason);
console.error("Explanation details:", dt.invalidExplanation);
}
})();
import { DateTime } from 'luxon';
/**
* Mapping for common abbreviations to IANA zones
* to ensure parsing doesn't fail on systems with limited ICU data.
*/
const ZONE_MAP = {
'EET': 'Europe/Helsinki',
'EST': 'America/New_York',
'CET': 'Europe/Paris',
'PST': 'America/Los_Angeles'
};
const INPUT = '2020-11-16 13:21:41 +0200 EET';
const FULL_FORMAT = "yyyy-MM-dd HH:mm:ss ZZZ z";
const FALLBACK_FORMAT = "yyyy-MM-dd HH:mm:ss ZZZ";
const parseDateSafely = (dateStr) => {
console.info(`--- Parsing: ${dateStr} ---`);
// 1. Attempt Standard Parse
let dt = DateTime.fromFormat(dateStr, FULL_FORMAT, { setZone: true });
// 2. Explanation for Debugging
const explanation = DateTime.fromFormatExplain(dateStr, FULL_FORMAT);
if (!dt.isValid) {
console.warn(`[!] Initial parse failed: ${dt.invalidReason}`);
// 3. Fallback: Strip the abbreviation and map it manually
const parts = dateStr.split(' ');
const abbr = parts.pop(); // Extracts 'EET'
const baseDate = parts.join(' '); // '2020-11-16 13:21:41 +0200'
const mappedZone = ZONE_MAP[abbr] || 'UTC';
dt = DateTime.fromFormat(baseDate, FALLBACK_FORMAT, {
zone: mappedZone
});
console.info(`[✓] Fallback applied using mapping: ${abbr} -> ${mappedZone}`);
}
return { dt, explanation };
};
// Execution
(() => {
const { dt, explanation } = parseDateSafely(INPUT);
console.log("\n--- Parsing Explanation ---");
console.dir(explanation, { depth: 2 });
console.log("\n--- Final DateTime Object ---");
if (dt.isValid) {
console.log({
iso: dt.toISOString(),
zone: dt.zoneName,
local: dt.toString(),
offset: dt.offsetNameShort
});
} else {
console.error("Critical Failure: Date still invalid.");
}
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment