When you are working with dates and times in loops or cards, remembering the different formats can be challenging. To that end, I put together a component and a shortcode as seen here. Feel free to use these as you see fit. You can also just go to the official WP documentation linked above.
<?php
/**
* Shortcode: [fw_date_formatter]
*/
add_shortcode( 'fw_date_formatter', 'fw_date_formatter_shortcode' );
function fw_date_formatter_shortcode( $atts = [] ) {
static $instance = 0;
static $script_printed = false;
$instance++;
$atts = shortcode_atts(
[
'date' => '1/1/2027',
'time' => '10:30',
'ampm' => 'PM',
'format' => 'date_long',
'show_format' => 'true',
],
$atts,
'fw_date_formatter'
);
$id = 'fw-date-formatter-' . $instance;
$formats = [
'date_full' => 'Date Full',
'date_long' => 'Date Long',
'date_medium' => 'Date Medium',
'date_short' => 'Date Short',
'y_m_d' => 'Y-m-d',
'iso_datetime' => 'ISO Date and Time',
'time_full' => 'Time Full',
'time_long' => 'Time Long',
'time_medium' => 'Time Medium',
'time_short' => 'Time Short',
'datetime_full' => 'Date and Time Full',
'datetime_long' => 'Date and Time Long',
'datetime_short' => 'Date and Time Short',
];
ob_start();
?>
<div
id="<?php echo esc_attr( $id ); ?>"
class="fw-date-formatter"
data-fw-date-formatter
>
<div class="fw-date-formatter__fields">
<div class="fw-date-formatter__field">
<label class="fw-date-formatter__label" for="<?php echo esc_attr( $id ); ?>-date">
Date
</label>
<input
class="fw-date-formatter__input"
id="<?php echo esc_attr( $id ); ?>-date"
type="text"
value="<?php echo esc_attr( $atts['date'] ); ?>"
placeholder="m/d/yyyy"
data-fw-date-input
>
</div>
<div class="fw-date-formatter__field">
<label class="fw-date-formatter__label" for="<?php echo esc_attr( $id ); ?>-time">
Time
</label>
<input
class="fw-date-formatter__input"
id="<?php echo esc_attr( $id ); ?>-time"
type="text"
value="<?php echo esc_attr( $atts['time'] ); ?>"
placeholder="hh:mm"
data-fw-time-input
>
</div>
<div class="fw-date-formatter__field">
<label class="fw-date-formatter__label" for="<?php echo esc_attr( $id ); ?>-ampm">
AM/PM
</label>
<select
class="fw-date-formatter__select"
id="<?php echo esc_attr( $id ); ?>-ampm"
data-fw-ampm-input
>
<option value="24H" <?php selected( $atts['ampm'], '24H' ); ?>>24H</option>
<option value="AM" <?php selected( $atts['ampm'], 'AM' ); ?>>AM</option>
<option value="PM" <?php selected( $atts['ampm'], 'PM' ); ?>>PM</option>
</select>
</div>
<div class="fw-date-formatter__field">
<label class="fw-date-formatter__label" for="<?php echo esc_attr( $id ); ?>-format">
Format
</label>
<select
class="fw-date-formatter__select"
id="<?php echo esc_attr( $id ); ?>-format"
data-fw-format-input
>
<?php foreach ( $formats as $value => $label ) : ?>
<option value="<?php echo esc_attr( $value ); ?>" <?php selected( $atts['format'], $value ); ?>>
<?php echo esc_html( $label ); ?>
</option>
<?php endforeach; ?>
</select>
</div>
<div class="fw-date-formatter__field fw-date-formatter__field--checkbox">
<input
class="fw-date-formatter__checkbox"
id="<?php echo esc_attr( $id ); ?>-show-format"
type="checkbox"
data-fw-show-format-input
<?php checked( filter_var( $atts['show_format'], FILTER_VALIDATE_BOOLEAN ) ); ?>
>
<label class="fw-date-formatter__label" for="<?php echo esc_attr( $id ); ?>-show-format">
Show dateFormat
</label>
</div>
</div>
<p class="fw-date-formatter__result">
<time class="fw-date-formatter__output" data-fw-date-output></time>
</p>
</div>
<?php if ( ! $script_printed ) : ?>
<script>
(() => {
const wpFormatMap = {
date_full: 'l, F j, Y',
date_long: 'F j, Y',
date_medium: 'M j, Y',
date_short: 'n/j/y',
y_m_d: 'Y-m-d',
iso_datetime: 'c',
time_full: 'g:i:s A T',
time_long: 'g:i:s A',
time_medium: 'g:i A',
time_short: 'g:i A',
datetime_full: 'l, F j, Y g:i A',
datetime_long: 'F j, Y g:i A',
datetime_short: 'n/j/y g:i A',
};
const monthsFull = ['January','February','March','April','May','June','July','August','September','October','November','December'];
const monthsShort = ['Jan','Feb','Mar','Apr','May','Jun','Jul','Aug','Sep','Oct','Nov','Dec'];
const daysFull = ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'];
const pad = (value) => String(value).padStart(2, '0');
function formatWithWpTokens(date, format) {
const hours24 = date.getHours();
const hours12 = hours24 % 12 || 12;
const map = {
Y: date.getFullYear(),
y: String(date.getFullYear()).slice(-2),
F: monthsFull[date.getMonth()],
M: monthsShort[date.getMonth()],
m: pad(date.getMonth() + 1),
n: date.getMonth() + 1,
d: pad(date.getDate()),
j: date.getDate(),
l: daysFull[date.getDay()],
H: pad(hours24),
G: hours24,
h: pad(hours12),
g: hours12,
i: pad(date.getMinutes()),
s: pad(date.getSeconds()),
A: hours24 >= 12 ? 'PM' : 'AM',
a: hours24 >= 12 ? 'pm' : 'am',
T: Intl.DateTimeFormat('en-US', { timeZoneName: 'short' })
.formatToParts(date)
.find((part) => part.type === 'timeZoneName')?.value || '',
c: date.toISOString(),
};
return format.replace(/[YyFMmndjlHGhgisAaTc]/g, (token) => map[token] ?? token);
}
function updateFormatter(formatter) {
const dateInput = formatter.querySelector('[data-fw-date-input]');
const timeInput = formatter.querySelector('[data-fw-time-input]');
const ampmInput = formatter.querySelector('[data-fw-ampm-input]');
const formatInput = formatter.querySelector('[data-fw-format-input]');
const showFormatInput = formatter.querySelector('[data-fw-show-format-input]');
const output = formatter.querySelector('[data-fw-date-output]');
if (!dateInput || !timeInput || !ampmInput || !formatInput || !output) return;
const dateValue = dateInput.value.trim();
const timeValue = timeInput.value.trim();
const ampm = ampmInput.value.trim();
const formatKey = formatInput.value || 'date_long';
const format = wpFormatMap[formatKey] || 'F j, Y';
const combinedTime = `${timeValue || '00:00'} ${ampm && ampm !== '24H' ? ampm : ''}`.trim();
const date = new Date(`${dateValue} ${combinedTime}`);
if (Number.isNaN(date.getTime())) {
output.textContent = 'Enter a valid date and time.';
output.removeAttribute('datetime');
return;
}
const formatted = formatWithWpTokens(date, format);
const showFormat = showFormatInput?.checked;
output.textContent = showFormat
? `${formatted} (use dateFormat '${format}')`
: formatted;
output.setAttribute('datetime', date.toISOString());
}
document.querySelectorAll('[data-fw-date-formatter]').forEach((formatter) => {
updateFormatter(formatter);
formatter.addEventListener('input', () => updateFormatter(formatter));
formatter.addEventListener('change', () => updateFormatter(formatter));
});
})();
</script>
<?php $script_printed = true; ?>
<?php endif; ?>
<?php
return ob_get_clean();
}
Leave a Reply