@craftercms/studio-ui
Version:
Services, components, models & utils to build CrafterCMS authoring extensions.
140 lines (138 loc) • 5.24 kB
JavaScript
/*
* Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License version 3 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
/*
* Copyright (C) 2007-2022 Crafter Software Corporation. All Rights Reserved.
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 3 as published by
* the Free Software Foundation.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
import moment from 'moment-timezone';
import { defineMessages } from 'react-intl';
import { getCurrentIntl } from './i18n';
const translations = defineMessages({
ordinals: {
id: 'dateTime.ordinals',
defaultMessage: '{day, selectordinal, one {#st} two {#nd} few {#rd} other {#th}}'
}
});
export const getTimezones = ((zoneNames) => {
let timeZones = [];
zoneNames.forEach((name, i) => {
timeZones.push({
name,
offset: `${moment.tz(zoneNames[i]).format('Z')}`
});
});
const sorted = timeZones.sort((a, b) => (parseInt(a.offset) > parseInt(b.offset) ? 1 : -1));
return () => sorted;
})(moment.tz.names());
export function asDayMonthDateTime(date) {
const parts = getCurrentIntl().formatDateToParts(date, {
month: 'long',
day: 'numeric',
weekday: 'long',
year: 'numeric'
});
return `${parts[0].value} ${parts[2].value} ${getCurrentIntl().formatMessage(translations.ordinals, {
day: parts[4].value
})} ${parts[6].value} @ ${getCurrentIntl().formatTime(date)}`;
}
export function asLocalizedDateTime(date, localeCode, dateTimeFormatOptions) {
return new Intl.DateTimeFormat(localeCode, dateTimeFormatOptions).format(new Date(date));
}
export function getUserTimeZone() {
return Intl.DateTimeFormat().resolvedOptions().timeZone;
}
export function getUserLocaleCode() {
return Intl.DateTimeFormat().resolvedOptions().locale;
}
/**
* Create ISO 8601 string
**/
export const create8601String = (date, time, offset) => `${date}T${time}${offset}`;
/**
* Returns an array as ['yyyy-mm-dd', 'hh:mm:ss', '+/-nn:nn'] out of a ISO 8601 date string
**/
export const get8601Pieces = (date) => {
const format = moment(date).format();
// Trying to match either:
// - 2024-10-31T10:30:00+01:00
// - 2024-10-31T09:30:00Z
const pieces = format.match(/(\d{4}-\d{2}-\d{2})T(\d{2}:\d{2}:\d{2})(.{6}|.)/);
return [pieces[1], pieces[2], pieces[3]];
};
export function isSameDay(date1, date2) {
return (
date1.getFullYear() === date2.getFullYear() &&
date1.getMonth() === date2.getMonth() &&
date1.getDate() === date2.getDate()
);
}
/**
* Returns the Z offset (e.g. +01:00) from the offset number that represents the difference,
* in minutes, between this date as evaluated in the UTC time zone, and the same date as evaluated
* in the local time zone
**/
export function getFormattedGmtOffsetFromTimezoneOffset(timezoneOffset) {
const offsetHours = Math.floor(Math.abs(timezoneOffset) / 60);
const offsetMinutes = Math.abs(timezoneOffset) % 60;
const sign = timezoneOffset <= 0 ? '+' : '-';
return `${sign}${String(offsetHours).padStart(2, '0')}:${String(offsetMinutes).padStart(2, '0')}`; // e.g., "+02:00"
}
/**
* Returns true if the date object is a valid date, false otherwise
**/
export function isValidDate(date) {
return date instanceof Date && !isNaN(date.getTime());
}
/**
* Returns the Z offset (e.g. +01:00) of a timezone name, considering daylight savings of the date.
**/
export function getZDateOffset(date, timezone) {
return moment(date).clone().tz(timezone).format('Z');
}
/**
* Creates a Date object that's the same moment in time as the original date but expressed in the target timezone
**/
export function createTransposedToTimezoneDate(date, targetTimezone) {
const pieces = get8601Pieces(date);
const targetOffset = getZDateOffset(date, targetTimezone);
const dateString = create8601String(pieces[0], pieces[1], targetOffset);
return new Date(dateString);
}
/**
* Creates a date that's at least half hour from now.
**/
export function createAtLeastHalfHourInFutureDate() {
const reference = new Date();
const date = new Date();
date.setHours(date.getHours() + 1);
date.setMinutes(0, 0, 0);
const diffMs = date.getTime() - reference.getTime();
if (diffMs < 1800000) {
date.setMinutes(date.getMinutes() + 30);
}
return date;
}