Dates
Moment.js-style chainable date manipulation without the bloat.
Creating Dates
Create DommaDate instances from various inputs.
// Current date/time
D()
D(new Date())
// From string
D('2025-12-25')
D('2025-12-25T10:30:00')
D('December 25, 2025')
// From timestamp
D(1735084800000)
// From Date object
D(new Date(2025, 11, 25))
// Parse with static method
Domma.dates.parse('2025-12-25')
// Get current timestamp
Domma.dates.now() // Returns timestamp number
<div class="flex gap-2 flex-wrap mb-3">
<button type="button" class="btn btn-outline btn-sm" data-create="now">D()</button>
<button type="button" class="btn btn-outline btn-sm" data-create="string">D('2025-12-25')</button>
<button type="button" class="btn btn-outline btn-sm" data-create="timestamp">D(1735084800000)</button>
<button type="button" class="btn btn-outline btn-sm" data-create="static">dates.now()</button>
</div>
<div class="demo-result-style" id="create-result">Click a button to create a date</div>/**
* Try It - from public/showcase/dates.
*/
export function mount(root) {
// Create demos
$('[data-create]').on('click', function () {
const type = $(this).data('create');
let result, code;
switch (type) {
case 'now':
result = D();
code = "D()";
break;
case 'string':
result = D('2025-12-25');
code = "D('2025-12-25')";
break;
case 'timestamp':
result = D(1735084800000);
code = "D(1735084800000)";
break;
case 'static':
result = Domma.dates.now();
code = "Domma.dates.now()";
$(root).find('#create-result').text(`${code} = ${result}`);
return;
}
$(root).find('#create-result').text(`${code}.format('MMMM D, YYYY HH:mm:ss')\n= "${result.format('MMMM D, YYYY HH:mm:ss')}"`);
});
}Formatting
Format dates using tokens similar to Moment.js.
Format Tokens
<div class="format-token">YYYY <span>2025</span></div>
<div class="format-token">YY <span>25</span></div>
<div class="format-token">MMMM <span>December</span></div>
<div class="format-token">MMM <span>Dec</span></div>
<div class="format-token">MM <span>12</span></div>
<div class="format-token">M <span>12</span></div>
<div class="format-token">DD <span>25</span></div>
<div class="format-token">D <span>25</span></div>
<div class="format-token">dddd <span>Thursday</span></div>
<div class="format-token">ddd <span>Thu</span></div>
<div class="format-token">dd <span>Th</span></div>
<div class="format-token">d <span>4</span></div>
<div class="format-token">HH <span>14</span></div>
<div class="format-token">H <span>14</span></div>
<div class="format-token">hh <span>02</span></div>
<div class="format-token">h <span>2</span></div>
<div class="format-token">mm <span>30</span></div>
<div class="format-token">m <span>30</span></div>
<div class="format-token">ss <span>45</span></div>
<div class="format-token">s <span>45</span></div>
<div class="format-token">A <span>PM</span></div>
<div class="format-token">a <span>pm</span></div>D().format('YYYY-MM-DD') // '2025-12-03'
D().format('MMMM D, YYYY') // 'December 3, 2025'
D().format('dddd, MMMM Do YYYY') // 'Wednesday, December 3rd 2025'
D().format('h:mm A') // '2:30 PM'
D().format('HH:mm:ss') // '14:30:45'
D().format('MMM D, YYYY h:mm A') // 'Dec 3, 2025 2:30 PM'
// ISO format
D().toISOString() // '2025-12-03T14:30:45.000Z'
// Unix timestamp
D().unix() // 1733236245
<input type="text" id="format-input" class="form-input mb-3" value="MMMM D, YYYY h:mm A" placeholder="Enter format string">
<div class="flex gap-2 flex-wrap mb-3">
<button type="button" class="btn btn-outline btn-sm" data-format="YYYY-MM-DD">YYYY-MM-DD</button>
<button type="button" class="btn btn-outline btn-sm" data-format="MMMM D, YYYY">MMMM D, YYYY</button>
<button type="button" class="btn btn-outline btn-sm" data-format="dddd, MMM D">dddd, MMM D</button>
<button type="button" class="btn btn-outline btn-sm" data-format="h:mm A">h:mm A</button>
<button type="button" class="btn btn-primary btn-sm" id="format-btn">Format</button>
</div>
<div class="demo-result-style" id="format-result">Click a format or enter your own</div>/**
* Try It - from public/showcase/dates.
*/
export function mount(root) {
// Format demos
$('[data-format]').on('click', function () {
const format = $(this).data('format');
$(root).find('#format-input').val(format);
$(root).find('#format-btn').trigger('click');
});
$(root).find('#format-btn').on('click', function () {
const format = $(root).find('#format-input').val();
const result = D().format(format);
$(root).find('#format-result').text(`D().format('${format}')\n= "${result}"`);
});
}Manipulation
Add, subtract, and modify dates with a chainable API.
add()
subtract()
startOf()
endOf()
set()
clone()
// Add time
D().add(7, 'days').format('MMM D')
D().add(1, 'month').format('MMM D')
D().add(2, 'hours').format('h:mm A')
// Subtract time
D().subtract(1, 'week').format('MMM D')
D().subtract(3, 'months').format('MMM YYYY')
// Units: years, months, weeks, days, hours, minutes, seconds
// Start/end of period
D().startOf('day') // 00:00:00.000
D().startOf('month') // First day of month
D().startOf('year') // January 1st
D().endOf('day') // 23:59:59.999
D().endOf('month') // Last day of month
// Set specific values
D().set('year', 2030)
D().set('month', 0) // January (0-indexed)
D().set('date', 15)
// Chain operations
D()
.add(1, 'month')
.startOf('month')
.format('MMMM D, YYYY')
// Clone to avoid mutation
const date = D('2025-06-15');
const nextMonth = date.clone().add(1, 'month');
Starting from:
<p class="text-sm text-muted mb-3">Starting from: <strong id="manip-base"></strong></p>
<div class="flex gap-2 flex-wrap mb-3">
<button type="button" class="btn btn-outline btn-sm" data-manip="add-7-days">+7 days</button>
<button type="button" class="btn btn-outline btn-sm" data-manip="add-1-month">+1 month</button>
<button type="button" class="btn btn-outline btn-sm" data-manip="sub-1-week">-1 week</button>
<button type="button" class="btn btn-outline btn-sm" data-manip="startOf-month">startOf('month')</button>
<button type="button" class="btn btn-outline btn-sm" data-manip="endOf-month">endOf('month')</button>
<button type="button" class="btn btn-outline btn-sm" data-manip="startOf-year">startOf('year')</button>
</div>
<div class="demo-result-style" id="manip-result">Click a button to manipulate the date</div>/**
* Try It - from public/showcase/dates.
*/
export function mount(root) {
// Update base date display
$(root).find('#manip-base').text(D().format('MMMM D, YYYY'));
// Manipulation demos
$('[data-manip]').on('click', function () {
const manip = $(this).data('manip');
let result, code;
const base = D();
switch (manip) {
case 'add-7-days':
result = base.clone().add(7, 'days');
code = "D().add(7, 'days')";
break;
case 'add-1-month':
result = base.clone().add(1, 'month');
code = "D().add(1, 'month')";
break;
case 'sub-1-week':
result = base.clone().subtract(1, 'week');
code = "D().subtract(1, 'week')";
break;
case 'startOf-month':
result = base.clone().startOf('month');
code = "D().startOf('month')";
break;
case 'endOf-month':
result = base.clone().endOf('month');
code = "D().endOf('month')";
break;
case 'startOf-year':
result = base.clone().startOf('year');
code = "D().startOf('year')";
break;
}
$(root).find('#manip-result').text(`${code}.format('MMMM D, YYYY HH:mm:ss')\n= "${result.format('MMMM D, YYYY HH:mm:ss')}"`);
});
}Getters & Setters
Get and set individual date/time components.
year()
month()
date()
day()
hour()
minute()
second()
millisecond()
dayOfYear()
week()
quarter()
const d = D('2025-12-25T14:30:45');
// Getters (no argument)
d.year() // 2025
d.month() // 11 (December, 0-indexed)
d.date() // 25
d.day() // 4 (Thursday, 0=Sunday)
d.hour() // 14
d.minute() // 30
d.second() // 45
d.dayOfYear() // 359
d.week() // 52
d.quarter() // 4
// Setters (with argument)
d.year(2030)
d.month(5) // June
d.date(1)
d.hour(9)
// Get native Date object
d.toDate() // Returns Date instance
// Read selected date parts
const parts = { year: d.year(), month: d.month(), date: d.date() };
<div class="grid grid-cols-4 gap-3" id="getters-display">
<!-- Filled by JS -->
</div>/**
* Current Date Components - from public/showcase/dates.
*/
export function mount(root) {
// Getters display
function updateGetters() {
const now = D();
const getters = [
['year()', now.year()],
['month()', now.month()],
['date()', now.date()],
['day()', now.day()],
['hour()', now.hour()],
['minute()', now.minute()],
['second()', now.second()],
['dayOfYear()', now.dayOfYear()],
['week()', now.week()],
['quarter()', now.quarter()],
['daysInMonth()', now.daysInMonth()],
['isLeapYear()', now.isLeapYear()]
];
$(root).find('#getters-display').html(getters.map(([name, value]) =>
`<div class="p-3 bg-white rounded border">
<div class="text-sm text-muted">${name}</div>
<div class="font-semibold">${value}</div>
</div>`
).join(''));
}
updateGetters();
}Relative Time
Display human-readable relative time strings.
fromNow()
to()
// Time from now
D().subtract(5, 'minutes').fromNow() // 'a few minutes ago'
D().subtract(2, 'hours').fromNow() // '2 hours ago'
D().subtract(3, 'days').fromNow() // '3 days ago'
D().add(1, 'week').fromNow() // 'in 7 days'
// Time from another date
const past = D('2025-01-01');
const future = D('2025-12-31');
past.fromNow(future) // '12 months ago'
future.fromNow(past) // 'in 12 months'
// Time to now/another date
D().add(2, 'weeks').fromNow() // 'in 2 weeks'
past.to(future) // 'in 12 months'
<div class="flex gap-2 flex-wrap mb-3">
<button type="button" class="btn btn-outline btn-sm" data-relative="-5-minutes">5 minutes ago</button>
<button type="button" class="btn btn-outline btn-sm" data-relative="-2-hours">2 hours ago</button>
<button type="button" class="btn btn-outline btn-sm" data-relative="-3-days">3 days ago</button>
<button type="button" class="btn btn-outline btn-sm" data-relative="-2-weeks">2 weeks ago</button>
<button type="button" class="btn btn-outline btn-sm" data-relative="1-hour">in 1 hour</button>
<button type="button" class="btn btn-outline btn-sm" data-relative="7-days">in 7 days</button>
<button type="button" class="btn btn-outline btn-sm" data-relative="1-month">in 1 month</button>
</div>
<div class="demo-result-style" id="relative-result">Click a button to see relative time</div>/**
* Try It - from public/showcase/dates.
*/
export function mount(root) {
// Relative time demos
$('[data-relative]').on('click', function () {
const rel = $(this).data('relative');
const parts = rel.split('-');
const negative = parts[0] === '';
const amount = parseInt(negative ? parts[1] : parts[0]);
const unit = negative ? parts[2] : parts[1];
let result;
if (negative) {
result = D().subtract(amount, unit);
} else {
result = D().add(amount, unit);
}
const fromNow = result.fromNow();
const formatted = result.format('MMMM D, YYYY h:mm A');
$(root).find('#relative-result').text(`Date: ${formatted}\nfromNow(): "${fromNow}"`);
});
}Comparison & Difference
Compare dates and calculate differences.
isBefore()
isAfter()
isSame()
isBetween()
diff()
const jan = D('2025-01-15');
const dec = D('2025-12-25');
// Comparison
jan.isBefore(dec) // true
dec.isAfter(jan) // true
jan.isSame(jan.clone()) // true
// Compare by unit
D('2025-01-15').isSame('2025-01-20', 'month') // true
D('2025-01-15').isSame('2025-02-15', 'year') // true
// Range check
const mid = D('2025-06-15');
mid.isBetween(jan, dec) // true
mid.isBetween(jan, dec, 'month') // true
// Difference
dec.diff(jan, 'days') // 344
dec.diff(jan, 'months') // 11
dec.diff(jan, 'weeks') // 49
// Float difference
dec.diff(jan, 'months', true) // 11.33...
<div class="grid grid-cols-2 gap-4 mb-3">
<div>
<label class="form-label">Start Date</label>
<input type="date" id="diff-start" class="form-input" value="2025-01-01">
</div>
<div>
<label class="form-label">End Date</label>
<input type="date" id="diff-end" class="form-input" value="2025-12-31">
</div>
</div>
<button type="button" class="btn btn-primary btn-sm mb-3" id="diff-calc">Calculate Difference</button>
<div class="demo-result-style" id="diff-result">Enter dates and click Calculate</div>/**
* Date Difference - from public/showcase/dates.
*/
export function mount(root) {
// Diff calculator
$(root).find('#diff-calc').on('click', function () {
const start = D($(root).find('#diff-start').val());
const end = D($(root).find('#diff-end').val());
const days = end.diff(start, 'days');
const weeks = end.diff(start, 'weeks');
const months = end.diff(start, 'months');
const years = end.diff(start, 'years', true).toFixed(2);
$(root).find('#diff-result').text(
`Days: ${days}\n` +
`Weeks: ${weeks}\n` +
`Months: ${months}\n` +
`Years: ${years}`
);
});
}Validation & Utilities
Validate dates and use helpful static methods.
isValid()
isLeapYear()
daysInMonth()
dates.isValid()
dates.min()
dates.max()
// Instance validation
D('2025-12-25').isValid() // true
D('invalid').isValid() // false
// Static validation
Domma.dates.isValid('2025-02-30') // false (Feb 30 doesn't exist)
Domma.dates.isValid('2025-12-25') // true
// Leap year check
D('2024-01-01').isLeapYear() // true
D('2025-01-01').isLeapYear() // false
// Days in month
D('2025-02-01').daysInMonth() // 28
D('2024-02-01').daysInMonth() // 29 (leap year)
D('2025-12-01').daysInMonth() // 31
// Min/Max of dates
const dates = [D('2025-03-15'), D('2025-01-01'), D('2025-06-20')];
Domma.dates.min(dates).format('MMM D') // 'Jan 1'
Domma.dates.max(dates).format('MMM D') // 'Jun 20'
<div class="flex gap-2 flex-wrap mb-3">
<button type="button" class="btn btn-outline btn-sm" data-valid="valid">isValid('2025-12-25')</button>
<button type="button" class="btn btn-outline btn-sm" data-valid="invalid">isValid('2025-02-30')</button>
<button type="button" class="btn btn-outline btn-sm" data-valid="leap2024">isLeapYear(2024)</button>
<button type="button" class="btn btn-outline btn-sm" data-valid="leap2025">isLeapYear(2025)</button>
<button type="button" class="btn btn-outline btn-sm" data-valid="days">daysInMonth(Feb 2025)</button>
</div>
<div class="demo-result-style" id="valid-result">Click a button to see result</div>/**
* Try It - from public/showcase/dates.
*/
export function mount(root) {
// Validation demos
$('[data-valid]').on('click', function () {
const type = $(this).data('valid');
let result, code;
switch (type) {
case 'valid':
result = D('2025-12-25').isValid();
code = "D('2025-12-25').isValid()";
break;
case 'invalid':
result = D('2025-02-30').isValid();
code = "D('2025-02-30').isValid()";
break;
case 'leap2024':
result = D('2024-01-01').isLeapYear();
code = "D('2024-01-01').isLeapYear()";
break;
case 'leap2025':
result = D('2025-01-01').isLeapYear();
code = "D('2025-01-01').isLeapYear()";
break;
case 'days':
result = D('2025-02-01').daysInMonth();
code = "D('2025-02-01').daysInMonth()";
break;
}
$(root).find('#valid-result').text(`${code} = ${result}`);
});
}Complete Method Reference
Instance Methods
format()
toISOString()
toDate()
unix()
valueOf()
clone()
add()
subtract()
startOf()
endOf()
set()
year()
month()
date()
day()
hour()
minute()
second()
millisecond()
dayOfYear()
week()
quarter()
daysInMonth()
isLeapYear()
isValid()
isBefore()
isAfter()
isSame()
isBetween()
diff()
fromNow()
to()
Static Methods
dates.now()
dates.parse()
dates.isValid()
dates.min()
dates.max()