Skip to content

Commit

Permalink
Feat : custom timezone spec (nhn#723) (nhn#721)
Browse files Browse the repository at this point in the history
* feat: set custom timezone options from New York os time to Seoul custom timezone

* feat: resolve custom timezone spec

* refactor: refactor timezone diff offset logic

* test: resolve broken TC

* test: add initUtil TC

* refactor: support breaking changes for timezoneOffset property

* style: revert eslint style

* refactor: remove unnecessary code

* test: resolve broken TC

* refactor: refactor duration code

* refactor: remove console log

* fix: recalculate detail popup time

* fix: resolve creation popup for using dst timezone

* refactor: apply PR feedbacks

* refactor: add type declaration for timezone option and refactor timezone example

* test: add intl polyfill for initUtil TC

* test: add weakmap polyfill for intl.dateTimeFormat polyfill

* test: add getCanonical polyfill

* test: add Set polyfill

* test: resolve TC

* test: resolve broken TC

* test: add require locale data

* test: add intl.numberFormat

* test: add intl.locale polyfill

* test: add numberformat local data

* test: change polyfill

* test: add locale data polyfill

* test: resolve broken TC

* test: remove numberformat locale-data polyfill

* test: resolve broken TC (locae data)

* chore: remove unnecessary dev dependency

* test: change intl polyfill

* test: add comment

* refactor: remove unnecessary title text
  • Loading branch information
jungeun-cho committed Dec 23, 2020
1 parent 03112f3 commit b2870fe
Show file tree
Hide file tree
Showing 18 changed files with 1,091 additions and 276 deletions.
28 changes: 19 additions & 9 deletions examples/example13-timezone.html
Original file line number Diff line number Diff line change
Expand Up @@ -38,22 +38,32 @@
<script src="https://uicdn.toast.com/tui.date-picker/v4.0.3/tui-date-picker.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.20.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/chance/1.0.13/chance.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-timezone/0.5.31/moment-timezone-with-data.js" integrity="sha512-ECoTMVFwwVtxjEBRjUMjviUd6hBjwDhBJI0+3W2YDs+ld5rHHUDr59T15gxwEPkGu5XLmkASUSvPgQe/Tpyodg==" crossorigin="anonymous"></script>
<script src="../dist/tui-calendar.js"></script>
<script src="./js/data/calendars.js"></script>
<script src="./js/data/schedules.js"></script>
<script type="text/javascript" class="code-js">
var cal = new tui.Calendar('#calendar', {
defaultView: 'week', // set 'week' or 'day'
timezones: [ // set timezone config
{
timezoneOffset: 540,
tooltip: 'Seoul'
timezone: {
zones: [
{
timezoneName: 'Asia/Seoul',
displayLabel: 'GMT+09:00',
tooltip: 'Seoul'
},
{
timezoneName: 'America/New_York',
displayLabel: 'GMT-05:00',
tooltip: 'New York',
}
],
offsetCalculator: function(timezoneName, timestamp){
// e.g. +09:00 => -540, -04:00 => 240
return moment.tz.zone(timezoneName).utcOffset(timestamp);
},
{
timezoneOffset: -420,
tooltip: 'Los Angeles'
}
],
},

taskView: false,
scheduleView: ['time']
});
Expand Down
7 changes: 6 additions & 1 deletion index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -200,9 +200,10 @@ export interface ISchedule {
}

export interface ITimezone {
timezoneOffset?: number;
timezoneName: string,
displayLabel?: string;
tooltip?: string;
timezoneOffset?: number;
}

export interface ICalendarInfo {
Expand Down Expand Up @@ -230,6 +231,10 @@ export interface IOptions {
useCreationPopup?: boolean;
useDetailPopup?: boolean;
timezones?: ITimezone[];
timezone?: {
zones: ITimezone[];
offsetCalculator: (timezoneName: string, timestamp: number) => number;
};
disableDblClick?: boolean;
disableClick?: boolean;
isReadOnly?: boolean;
Expand Down
8 changes: 8 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,14 @@
"index.d.ts"
],
"devDependencies": {
"@formatjs/intl": "^1.4.8",
"@formatjs/intl-datetimeformat": "^3.0.0",
"@formatjs/intl-getcanonicallocales": "^1.5.1",
"@formatjs/intl-locale": "^2.4.11",
"@formatjs/intl-numberformat": "^6.1.1",
"@formatjs/intl-pluralrules": "^4.0.1",
"css-loader": "^3.2.0",
"es6-set": "^0.1.5",
"eslint": "^4.19.1",
"eslint-config-tui": "^1.0.3",
"eslint-loader": "^2.0.0",
Expand Down Expand Up @@ -75,6 +82,7 @@
"tui-release-notes": "git+https://github.com/nhn/toast-ui.release-notes.git#v1.0.1",
"typescript": "^3.2.1",
"url-loader": "^1.0.1",
"weakmap-polyfill": "^2.0.2",
"webpack": "^4.13.0",
"webpack-cli": "^3.0.8",
"webpack-dev-server": "^3.11.0"
Expand Down
113 changes: 113 additions & 0 deletions src/js/common/intlUtil.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,113 @@
'use strict';

var util = require('tui-code-snippet');
var intlFormatter = {};
var intlUtil;

var typeToPos = {
year: 0,
month: 1,
day: 2,
hour: 3,
minute: 4,
second: 5
};

/**
* Extract date tokens (y, M, d, h, m, s) using the formatToParts() method.
* @param {Intl.DateTimeFormat} dtf - Intl.DateTimeFormat instance
* @param {Date} date - date object
* @returns {Array.<number>} An array of objects only containing the formatted date
*/
function parseOffset(dtf, date) {
var formatted = dtf.formatToParts(date);
var filled = [];
var formattedLength = formatted.length;
var i, pos;

for (i = 0; i < formattedLength; i += 1) {
pos = typeToPos[formatted[i].type];

if (!util.isUndefined(pos)) {
filled[pos] = parseInt(formatted[i].value, 10);
}
}

return filled;
}

/**
* The time zone offset is calculated from the difference between the current time and the time in a specific time zone.
* @param {Array.<number>} parts - An array of objects only containing the formatted date (e.g. [2020, 12, 14, 10, 15, 19])
* @param {Date} date - date object
* @returns {number} offset
*/
function calculateOffset(parts, date) {
var y = parts[0];
var M = parts[1];
var d = parts[2];
var h = parts[3];
var m = parts[4];
var s = parts[5];

var utc = new Date(Date.UTC(y, M - 1, d, h, m, s));
var offset = (utc - date) / 60 / 1000;

return Math.round(offset);
}

/**
* Check if browser supports Intl.DateTimeFormat.prototype.formatToParts API
* @returns {boolean} supported
*/
function supportIntl() {
/**
* IE9 and IE10 do not support Intl.DateTimeFormat
* IE11 does not support IANA timezone names
* http://kangax.github.io/compat-table/esintl/#test-DateTimeFormat_accepts_IANA_timezone_names
*/
return global.Intl && global.Intl.DateTimeFormat &&
util.isFunction(Intl.DateTimeFormat.prototype.formatToParts);
}

/**
* Return DateTimeFormat instance by timezone
* @param {string} timezoneName - timezone
* @returns {DateTimeFormat} Intl.DateTimeFormat instance
*/
function getIntlFormatter(timezoneName) {
if (!intlFormatter[timezoneName]) {
intlFormatter[timezoneName] = new Intl.DateTimeFormat('en-US', {
hourCycle: 'h23',
year: 'numeric',
month: 'numeric',
day: 'numeric',
hour: 'numeric',
minute: 'numeric',
second: 'numeric',
timeZone: timezoneName
});
}

return intlFormatter[timezoneName];
}

/**
* Get offset of the time by timezone
* @param {string} timezoneName - recognize the time zone names of the IANA time zone database, such as 'Asia/Seoul', 'America/New_York'
* @param {number} timestamp - timestamp
* @returns {number} offset
*/
function offsetCalculator(timezoneName, timestamp) {
var formatter = getIntlFormatter(timezoneName);
var date = new Date(timestamp);

return -calculateOffset(parseOffset(formatter, date), date);
}

intlUtil = {
supportIntl: supportIntl,
offsetCalculator: offsetCalculator
};

module.exports = intlUtil;
Loading

0 comments on commit b2870fe

Please sign in to comment.