forked from apache/superset
-
Notifications
You must be signed in to change notification settings - Fork 1
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add @superset-ui/time-format (apache#38)
feat: Add @superset-ui/time-format * update unit test (+6 squashed commits) Squashed commits: [5fae1ed] fix lint [7672544] support local and utc [c33fae7] update unit tests [97fdc0d] fix all unit tests [88e8029] add formatter code [a33c76c] initialize * update readme * add formatDate and formatDateVerbose equivalent * add unit test * extract constants * get to 100 coverage * update readme * Update preview test * explicitly disable magic number
- Loading branch information
Showing
22 changed files
with
782 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
## @superset-ui/time-format | ||
|
||
[![Version](https://img.shields.io/npm/v/@superset-ui/time-format.svg?style=flat)](https://img.shields.io/npm/v/@superset-ui/time-format.svg?style=flat) | ||
[![David (path)](https://img.shields.io/david/apache-superset/superset-ui.svg?path=packages%2Fsuperset-ui-time-format&style=flat-square)](https://david-dm.org/apache-superset/superset-ui?path=packages/superset-ui-time-format) | ||
|
||
Description | ||
|
||
#### Example usage | ||
|
||
Add `@superset-ui/time-format`, a module for formatting time. Functions `getTimeFormatter` and `formatTime` should be used instead of calling `d3.utcFormat` or `d3.timeFormat` directly. | ||
|
||
```js | ||
import { getTimeFormatter } from '@superset-ui/time-format'; | ||
const formatter = getTimeFormatter('%Y-%m-d'); | ||
console.log(formatter(new Date())); | ||
``` | ||
|
||
or | ||
|
||
```js | ||
import { formatTime } from '@superset-ui/time-format'; | ||
console.log(formatTime('%Y-%m-d', new Date())); | ||
``` | ||
|
||
It is powered by a registry to support registration of custom formatting, with fallback to `d3.utcFormat` or `d3.timeFormat` (if the formatId starts with `local!`) | ||
|
||
```js | ||
import { getTimeFormatterRegistry, formatTime, TimeFormatter } from '@superset-ui/time-format'; | ||
|
||
getTimeFormatterRegistry().registerValue('my_format', new TimeFormatter({ | ||
id: 'my_format', | ||
formatFunc: v => `my special format of ${utcFormat('%Y')(v)}` | ||
}); | ||
|
||
console.log(formatTime('my_format', new Date(2018))); | ||
// prints 'my special format of 2018' | ||
``` | ||
It also define constants for common d3 time formats. See [TimeFormats.js](https://github.com/apache-superset/superset-ui/blob/master/packages/superset-ui-time-format/src/TimeFormats.js). | ||
```js | ||
import { TimeFormats } from '@superset-ui/time-format'; | ||
|
||
TimeFormats.DATABASE_DATETIME // '%Y-%m-%d %H:%M:%S' | ||
TimeFormats.US_DATE // '%m/%d/%Y' | ||
``` | ||
#### API | ||
`fn(args)` | ||
- Do something | ||
### Development | ||
`@data-ui/build-config` is used to manage the build configuration for this package including babel | ||
builds, jest testing, eslint, and prettier. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
{ | ||
"name": "@superset-ui/time-format", | ||
"version": "0.0.0", | ||
"description": "Superset UI time-format", | ||
"sideEffects": false, | ||
"main": "lib/index.js", | ||
"module": "esm/index.js", | ||
"files": [ | ||
"esm", | ||
"lib" | ||
], | ||
"repository": { | ||
"type": "git", | ||
"url": "git+https://github.com/apache-superset/superset-ui.git" | ||
}, | ||
"keywords": [ | ||
"superset" | ||
], | ||
"author": "Superset", | ||
"license": "Apache-2.0", | ||
"bugs": { | ||
"url": "https://github.com/apache-superset/superset-ui/issues" | ||
}, | ||
"homepage": "https://github.com/apache-superset/superset-ui#readme", | ||
"publishConfig": { | ||
"access": "public" | ||
}, | ||
"dependencies": { | ||
"@superset-ui/core": "^0.6.0", | ||
"d3-time": "^1.0.10", | ||
"d3-time-format": "^2.1.3", | ||
"lodash": "^4.17.11" | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,8 @@ | ||
export const LOCAL_PREFIX = 'local!'; | ||
|
||
export const DATABASE_DATETIME = '%Y-%m-%d %H:%M:%S'; | ||
export const DATABASE_DATETIME_REVERSE = '%d-%m-%Y %H:%M:%S'; | ||
export const US_DATE = '%m/%d/%Y'; | ||
export const INTERNATIONAL_DATE = '%d/%m/%Y'; | ||
export const DATABASE_DATE = '%Y-%m-%d'; | ||
export const TIME = '%H:%M:%S'; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,35 @@ | ||
/* eslint-disable no-magic-numbers */ | ||
|
||
import { ExtensibleFunction, isRequired } from '@superset-ui/core'; | ||
|
||
export const PREVIEW_TIME = new Date(Date.UTC(2017, 1, 14, 11, 22, 33)); | ||
|
||
export default class TimeFormatter extends ExtensibleFunction { | ||
constructor({ | ||
id = isRequired('config.id'), | ||
label, | ||
description = '', | ||
formatFunc = isRequired('config.formatFunc'), | ||
useLocalTime = false, | ||
} = {}) { | ||
super((...args) => this.format(...args)); | ||
|
||
this.id = id; | ||
this.label = label || id; | ||
this.description = description; | ||
this.formatFunc = formatFunc; | ||
this.useLocalTime = useLocalTime; | ||
} | ||
|
||
format(value) { | ||
if (value === null || value === undefined) { | ||
return value; | ||
} | ||
|
||
return this.formatFunc(value); | ||
} | ||
|
||
preview(value = PREVIEW_TIME) { | ||
return `${value.toUTCString()} => ${this.format(value)}`; | ||
} | ||
} |
34 changes: 34 additions & 0 deletions
34
packages/superset-ui-time-format/src/TimeFormatterRegistry.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,34 @@ | ||
import { RegistryWithDefaultKey } from '@superset-ui/core'; | ||
import { DATABASE_DATETIME, LOCAL_PREFIX } from './TimeFormats'; | ||
import createD3TimeFormatter from './factories/createD3TimeFormatter'; | ||
|
||
const DEFAULT_FORMAT = DATABASE_DATETIME; | ||
|
||
export default class TimeFormatterRegistry extends RegistryWithDefaultKey { | ||
constructor() { | ||
super({ | ||
initialDefaultKey: DEFAULT_FORMAT, | ||
name: 'TimeFormatter', | ||
}); | ||
} | ||
|
||
get(format) { | ||
const targetFormat = format || this.defaultKey; | ||
|
||
if (this.has(targetFormat)) { | ||
return super.get(targetFormat); | ||
} | ||
|
||
// Create new formatter if does not exist | ||
const useLocalTime = targetFormat.startsWith(LOCAL_PREFIX); | ||
const formatString = targetFormat.replace(LOCAL_PREFIX, ''); | ||
const formatter = createD3TimeFormatter({ formatString, useLocalTime }); | ||
this.registerValue(targetFormat, formatter); | ||
|
||
return formatter; | ||
} | ||
|
||
format(format, value) { | ||
return this.get(format)(value); | ||
} | ||
} |
14 changes: 14 additions & 0 deletions
14
packages/superset-ui-time-format/src/TimeFormatterRegistrySingleton.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,14 @@ | ||
import { makeSingleton } from '@superset-ui/core'; | ||
import TimeFormatterRegistry from './TimeFormatterRegistry'; | ||
|
||
const getInstance = makeSingleton(TimeFormatterRegistry); | ||
|
||
export default getInstance; | ||
|
||
export function getTimeFormatter(formatId) { | ||
return getInstance().get(formatId); | ||
} | ||
|
||
export function formatTime(formatId, value) { | ||
return getInstance().format(formatId, value); | ||
} |
23 changes: 23 additions & 0 deletions
23
packages/superset-ui-time-format/src/factories/createD3TimeFormatter.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,23 @@ | ||
import { utcFormat, timeFormat } from 'd3-time-format'; | ||
import { isRequired } from '@superset-ui/core'; | ||
import TimeFormatter from '../TimeFormatter'; | ||
import { LOCAL_PREFIX } from '../TimeFormats'; | ||
|
||
export default function createD3TimeFormatter({ | ||
description, | ||
formatString = isRequired('formatString'), | ||
label, | ||
useLocalTime = false, | ||
}) { | ||
const id = useLocalTime ? `${LOCAL_PREFIX}${formatString}` : formatString; | ||
const format = useLocalTime ? timeFormat : utcFormat; | ||
const formatFunc = format(formatString); | ||
|
||
return new TimeFormatter({ | ||
description, | ||
formatFunc, | ||
id, | ||
label, | ||
useLocalTime, | ||
}); | ||
} |
69 changes: 69 additions & 0 deletions
69
packages/superset-ui-time-format/src/factories/createMultiFormatter.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
import { utcFormat, timeFormat } from 'd3-time-format'; | ||
import { utcUtils, localTimeUtils } from '../utils'; | ||
import TimeFormatter from '../TimeFormatter'; | ||
|
||
export default function createMultiFormatter({ | ||
id, | ||
label, | ||
description, | ||
formats = {}, | ||
useLocalTime = false, | ||
}) { | ||
const { | ||
millisecond = '.%L', | ||
second = ':%S', | ||
minute = '%I:%M', | ||
hour = '%I %p', | ||
day = '%a %d', | ||
week = '%b %d', | ||
month = '%B', | ||
year = '%Y', | ||
} = formats; | ||
|
||
const format = useLocalTime ? timeFormat : utcFormat; | ||
|
||
const formatMillisecond = format(millisecond); | ||
const formatSecond = format(second); | ||
const formatMinute = format(minute); | ||
const formatHour = format(hour); | ||
const formatDay = format(day); | ||
const formatFirstDayOfWeek = format(week); | ||
const formatMonth = format(month); | ||
const formatYear = format(year); | ||
|
||
const { | ||
hasMillisecond, | ||
hasSecond, | ||
hasMinute, | ||
hasHour, | ||
isNotFirstDayOfMonth, | ||
isNotFirstDayOfWeek, | ||
isNotFirstMonth, | ||
} = useLocalTime ? localTimeUtils : utcUtils; | ||
|
||
function multiFormatFunc(date) { | ||
if (hasMillisecond(date)) { | ||
return formatMillisecond; | ||
} else if (hasSecond(date)) { | ||
return formatSecond; | ||
} else if (hasMinute(date)) { | ||
return formatMinute; | ||
} else if (hasHour(date)) { | ||
return formatHour; | ||
} else if (isNotFirstDayOfMonth(date)) { | ||
return isNotFirstDayOfWeek(date) ? formatDay : formatFirstDayOfWeek; | ||
} else if (isNotFirstMonth(date)) { | ||
return formatMonth; | ||
} | ||
|
||
return formatYear; | ||
} | ||
|
||
return new TimeFormatter({ | ||
description, | ||
formatFunc: date => multiFormatFunc(date)(date), | ||
id, | ||
label, | ||
useLocalTime, | ||
}); | ||
} |
20 changes: 20 additions & 0 deletions
20
packages/superset-ui-time-format/src/formatters/smartDate.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* eslint-disable sort-keys */ | ||
|
||
import createMultiFormatter from '../factories/createMultiFormatter'; | ||
|
||
const smartDateFormatter = createMultiFormatter({ | ||
id: 'smart_date', | ||
label: 'Adaptative Formatting', | ||
formats: { | ||
millisecond: '.%Lms', | ||
second: ':%Ss', | ||
minute: '%I:%M', | ||
hour: '%I %p', | ||
day: '%a %d', | ||
week: '%b %d', | ||
month: '%B', | ||
year: '%Y', | ||
}, | ||
}); | ||
|
||
export default smartDateFormatter; |
20 changes: 20 additions & 0 deletions
20
packages/superset-ui-time-format/src/formatters/smartDateVerbose.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
/* eslint-disable sort-keys */ | ||
|
||
import createMultiFormatter from '../factories/createMultiFormatter'; | ||
|
||
const smartDateFormatter = createMultiFormatter({ | ||
id: 'smart_date_verbose', | ||
label: 'Verbose Adaptative Formatting', | ||
formats: { | ||
millisecond: '.%L', | ||
second: ':%S', | ||
minute: '%a %b %d, %I:%M %p', | ||
hour: '%a %b %d, %I %p', | ||
day: '%a %b %-e', | ||
week: '%a %b %-e', | ||
month: '%b %Y', | ||
year: '%Y', | ||
}, | ||
}); | ||
|
||
export default smartDateFormatter; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,10 @@ | ||
import * as TimeFormats from './TimeFormats'; | ||
|
||
export { | ||
default as getTimeFormatterRegistry, | ||
formatTime, | ||
getTimeFormatter, | ||
} from './TimeFormatterRegistrySingleton'; | ||
|
||
export { default as TimeFormatter, PREVIEW_TIME } from './TimeFormatter'; | ||
export { TimeFormats }; |
Oops, something went wrong.