Skip to content

Commit

Permalink
Make dateI18n returns be affected by gmt parameter (#18982)
Browse files Browse the repository at this point in the history
* Date: Make dateI18n returns be affected by `gmt` parameter

* Fixed capitalization in function name.

* Small refactor in internal function `buildMoment` to make it clear we’re transforming the same common Moment instance in distinct ways.

* Fixed documentation by adding a few references to wikipedia articles.

* Fixed JSdoc with links to Wikipedia.

Co-authored-by: Andrew Duthie <andrew@andrewduthie.com>
Co-authored-by: David Aguilera <david.aguilera@neliosoftware.com>
  • Loading branch information
3 people authored Apr 9, 2020
1 parent cee6439 commit 7f8c66d
Show file tree
Hide file tree
Showing 3 changed files with 582 additions and 39 deletions.
36 changes: 32 additions & 4 deletions packages/date/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,40 @@ _This package assumes that your code will run in an **ES2015+** environment. If

<a name="date" href="#date">#</a> **date**

Formats a date (like `date()` in PHP), in the site's timezone.
Formats a date (like `date()` in PHP).

_Related_

- <https://en.wikipedia.org/wiki/List_of_tz_database_time_zones>
- <https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC>

_Parameters_

- _dateFormat_ `string`: PHP-style formatting string. See php.net/date.
- _dateValue_ `(Date|string|Moment|null)`: Date object or string, parsable by moment.js.
- _timezone_ `(string|number|null)`: Timezone to output result in or a UTC offset. Defaults to timezone from site.

_Returns_

- `string`: Formatted date.
- `string`: Formatted date in English.

<a name="dateI18n" href="#dateI18n">#</a> **dateI18n**

Formats a date (like `date_i18n()` in PHP).
Formats a date (like `wp_date()` in PHP), translating it into site's locale.

Backward Compatibility Notice: if `timezone` is set to `true`, the function
behaves like `gmdateI18n`.

_Related_

- <https://en.wikipedia.org/wiki/List_of_tz_database_time_zones>
- <https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC>

_Parameters_

- _dateFormat_ `string`: PHP-style formatting string. See php.net/date.
- _dateValue_ `(Date|string|Moment|null)`: Date object or string, parsable by moment.js.
- _gmt_ `boolean`: True for GMT/UTC, false for site's timezone.
- _timezone_ `(string|number|boolean|null)`: Timezone to output result in or a UTC offset. Defaults to timezone from site. Notice: `boolean` is effectively deprecated, but still supported for backward compatibility reasons.

_Returns_

Expand Down Expand Up @@ -79,6 +93,20 @@ _Parameters_

_Returns_

- `string`: Formatted date in English.

<a name="gmdateI18n" href="#gmdateI18n">#</a> **gmdateI18n**

Formats a date (like `wp_date()` in PHP), translating it into site's locale
and using the UTC timezone.

_Parameters_

- _dateFormat_ `string`: PHP-style formatting string. See php.net/date.
- _dateValue_ `(Date|string|Moment|null)`: Date object or string, parsable by moment.js.

_Returns_

- `string`: Formatted date.

<a name="isInTheFuture" href="#isInTheFuture">#</a> **isInTheFuture**
Expand Down
148 changes: 116 additions & 32 deletions packages/date/src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@ import 'moment-timezone/moment-timezone-utils';

const WP_ZONE = 'WP';

// This regular expression tests positive for UTC offsets as described in ISO 8601.
// See: https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC
const VALID_UTC_OFFSET = /^[+-][0-1][0-9](:?[0-9][0-9])?$/;

// Changes made here will likely need to be made in `lib/client-assets.php` as
// well because it uses the `setSettings()` function to change these settings.
let settings = {
Expand Down Expand Up @@ -318,10 +322,10 @@ const formatMap = {
/**
* Formats a date. Does not alter the date's timezone.
*
* @param {string} dateFormat PHP-style formatting string.
* See php.net/date.
* @param {(Date|string|Moment|null)} dateValue Date object or string,
* parsable by moment.js.
* @param {string} dateFormat PHP-style formatting string.
* See php.net/date.
* @param {Date|string|Moment|null} dateValue Date object or string,
* parsable by moment.js.
*
* @return {string} Formatted date.
*/
Expand Down Expand Up @@ -357,57 +361,90 @@ export function format( dateFormat, dateValue = new Date() ) {
}

/**
* Formats a date (like `date()` in PHP), in the site's timezone.
* Formats a date (like `date()` in PHP).
*
* @param {string} dateFormat PHP-style formatting string.
* See php.net/date.
* @param {(Date|string|Moment|null)} dateValue Date object or string,
* parsable by moment.js.
* @param {string} dateFormat PHP-style formatting string.
* See php.net/date.
* @param {Date|string|Moment|null} dateValue Date object or string, parsable
* by moment.js.
* @param {string|number|null} timezone Timezone to output result in or a
* UTC offset. Defaults to timezone from
* site.
*
* @return {string} Formatted date.
* @see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
* @see https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC
*
* @return {string} Formatted date in English.
*/
export function date( dateFormat, dateValue = new Date() ) {
const offset = settings.timezone.offset * HOUR_IN_MINUTES;
const dateMoment = momentLib( dateValue ).utcOffset( offset, true );
export function date( dateFormat, dateValue = new Date(), timezone ) {
const dateMoment = buildMoment( dateValue, timezone );
return format( dateFormat, dateMoment );
}

/**
* Formats a date (like `date()` in PHP), in the UTC timezone.
*
* @param {string} dateFormat PHP-style formatting string.
* See php.net/date.
* @param {(Date|string|Moment|null)} dateValue Date object or string,
* parsable by moment.js.
* @param {string} dateFormat PHP-style formatting string.
* See php.net/date.
* @param {Date|string|Moment|null} dateValue Date object or string,
* parsable by moment.js.
*
* @return {string} Formatted date.
* @return {string} Formatted date in English.
*/
export function gmdate( dateFormat, dateValue = new Date() ) {
const dateMoment = momentLib( dateValue ).utc();
return format( dateFormat, dateMoment );
}

/**
* Formats a date (like `date_i18n()` in PHP).
* Formats a date (like `wp_date()` in PHP), translating it into site's locale.
*
* Backward Compatibility Notice: if `timezone` is set to `true`, the function
* behaves like `gmdateI18n`.
*
* @param {string} dateFormat PHP-style formatting string.
* See php.net/date.
* @param {Date|string|Moment|null} dateValue Date object or string, parsable by
* moment.js.
* @param {string|number|boolean|null} timezone Timezone to output result in or a
* UTC offset. Defaults to timezone from
* site. Notice: `boolean` is effectively
* deprecated, but still supported for
* backward compatibility reasons.
*
* @param {string} dateFormat PHP-style formatting string.
* See php.net/date.
* @param {(Date|string|Moment|null)} dateValue Date object or string,
* parsable by moment.js.
* @param {boolean} gmt True for GMT/UTC, false for
* site's timezone.
* @see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
* @see https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC
*
* @return {string} Formatted date.
*/
export function dateI18n( dateFormat, dateValue = new Date(), gmt = false ) {
// Defaults.
const offset = gmt ? 0 : settings.timezone.offset * HOUR_IN_MINUTES;
// Convert to moment object.
const dateMoment = momentLib( dateValue ).utcOffset( offset, true );
export function dateI18n( dateFormat, dateValue = new Date(), timezone ) {
if ( true === timezone ) {
return gmdateI18n( dateFormat, dateValue );
}

if ( false === timezone ) {
timezone = undefined;
}

// Set the locale.
const dateMoment = buildMoment( dateValue, timezone );
dateMoment.locale( settings.l10n.locale );
return format( dateFormat, dateMoment );
}

/**
* Formats a date (like `wp_date()` in PHP), translating it into site's locale
* and using the UTC timezone.
*
* @param {string} dateFormat PHP-style formatting string.
* See php.net/date.
* @param {Date|string|Moment|null} dateValue Date object or string,
* parsable by moment.js.
*
* @return {string} Formatted date.
*/
export function gmdateI18n( dateFormat, dateValue = new Date() ) {
const dateMoment = momentLib( dateValue ).utc();
dateMoment.locale( settings.l10n.locale );
// Format and return.
return format( dateFormat, dateMoment );
}

Expand Down Expand Up @@ -440,4 +477,51 @@ export function getDate( dateString ) {
return momentLib.tz( dateString, WP_ZONE ).toDate();
}

/**
* Creates a moment instance using the given timezone or, if none is provided, using global settings.
*
* @param {Date|string|Moment|null} dateValue Date object or string, parsable
* by moment.js.
* @param {string|number|null} timezone Timezone to output result in or a
* UTC offset. Defaults to timezone from
* site.
*
* @see https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
* @see https://en.wikipedia.org/wiki/ISO_8601#Time_offsets_from_UTC
*
* @return {Moment} a moment instance.
*/
function buildMoment( dateValue, timezone = '' ) {
const dateMoment = momentLib( dateValue );

if ( timezone && ! isUTCOffset( timezone ) ) {
return dateMoment.tz( timezone );
}

if ( timezone && isUTCOffset( timezone ) ) {
return dateMoment.utcOffset( timezone );
}

if ( settings.timezone.string ) {
return dateMoment.tz( settings.timezone.string );
}

return dateMoment.utcOffset( settings.timezone.offset );
}

/**
* Returns whether a certain UTC offset is valid or not.
*
* @param {number|string} offset a UTC offset.
*
* @return {boolean} whether a certain UTC offset is valid or not.
*/
function isUTCOffset( offset ) {
if ( 'number' === typeof offset ) {
return true;
}

return VALID_UTC_OFFSET.test( offset );
}

setupWPTimezone();
Loading

0 comments on commit 7f8c66d

Please sign in to comment.