diff --git a/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-big-number/BigNumber/BigNumberStories.tsx b/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-big-number/BigNumber/BigNumberStories.tsx
index d21e0dfb38..f38362afba 100644
--- a/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-big-number/BigNumber/BigNumberStories.tsx
+++ b/packages/superset-ui-demo/storybook/stories/plugins/legacy-preset-chart-big-number/BigNumber/BigNumberStories.tsx
@@ -37,6 +37,7 @@ const formData = {
metric: 'sum__SP_POP_TOTL',
showTrendLine: true,
startYAxisAtZero: true,
+ timeGrainSqla: 'P1Y',
vizType: 'big_number',
yAxisFormat: '.3s',
};
@@ -68,6 +69,19 @@ export const basicWithTrendline = () => (
/>
);
+export const weeklyTimeGranularity = () => (
+
+);
+
export const nullInTheMiddle = () => (
(
}}
formData={{
...formData,
- timeGrainSqla: 'P1Y',
timeRangeFixed: true,
}}
/>
diff --git a/plugins/legacy-preset-chart-big-number/src/utils/getTimeFormatterForGranularity.ts b/packages/superset-ui-time-format/src/factories/getTimeFormatterForGranularity.ts
similarity index 85%
rename from plugins/legacy-preset-chart-big-number/src/utils/getTimeFormatterForGranularity.ts
rename to packages/superset-ui-time-format/src/factories/getTimeFormatterForGranularity.ts
index 3655736de5..6f1964e34d 100644
--- a/plugins/legacy-preset-chart-big-number/src/utils/getTimeFormatterForGranularity.ts
+++ b/packages/superset-ui-time-format/src/factories/getTimeFormatterForGranularity.ts
@@ -16,12 +16,15 @@
* specific language governing permissions and limitations
* under the License.
*/
-import { getTimeFormatter, TimeFormats, smartDateVerboseFormatter } from '@superset-ui/time-format';
+import TimeFormats from '../TimeFormats';
+import { getTimeFormatter } from '../TimeFormatterRegistrySingleton';
+import smartDateVerboseFormatter from '../formatters/smartDateVerbose';
+import { TimeGranularity } from '../types';
// Translate time granularity to d3-format
const MINUTE = '%Y-%m-%d %H:%M';
-const SUNDAY_BASED_WEEK = '%Y W%U';
-const MONDAY_BASED_WEEK = '%Y W%W';
+const SUNDAY_BASED_WEEK = '%Y-%m-%d W%U';
+const MONDAY_BASED_WEEK = '%Y-%m-%d W%W';
const { DATABASE_DATE, DATABASE_DATETIME } = TimeFormats;
// search for `builtin_time_grains` in incubator-superset/superset/db_engine_specs/base.py
@@ -39,16 +42,13 @@ const formats = {
P1M: '%Y-%m', // month
'P0.25Y': '%Y Q%q', // quarter
P1Y: '%Y', // year
- // d3-time-format weeks does not support weeks start on Sunday
'1969-12-28T00:00:00Z/P1W': SUNDAY_BASED_WEEK, // 'week_start_sunday'
'1969-12-29T00:00:00Z/P1W': MONDAY_BASED_WEEK, // 'week_start_monday'
'P1W/1970-01-03T00:00:00Z': SUNDAY_BASED_WEEK, // 'week_ending_saturday'
'P1W/1970-01-04T00:00:00Z': MONDAY_BASED_WEEK, // 'week_ending_sunday'
};
-export type TimeGranularity = keyof typeof formats;
-
-export default function getTimeFormatterForGranularity(granularity: TimeGranularity | undefined) {
+export default function getTimeFormatterForGranularity(granularity?: TimeGranularity) {
return granularity && granularity in formats
? getTimeFormatter(formats[granularity])
: smartDateVerboseFormatter;
diff --git a/packages/superset-ui-time-format/src/index.ts b/packages/superset-ui-time-format/src/index.ts
index 729ad6a616..3c964ef133 100644
--- a/packages/superset-ui-time-format/src/index.ts
+++ b/packages/superset-ui-time-format/src/index.ts
@@ -9,6 +9,9 @@ export {
export { default as createD3TimeFormatter } from './factories/createD3TimeFormatter';
export { default as createMultiFormatter } from './factories/createMultiFormatter';
+export { default as getTimeFormatterForGranularity } from './factories/getTimeFormatterForGranularity';
export { default as smartDateFormatter } from './formatters/smartDate';
export { default as smartDateVerboseFormatter } from './formatters/smartDateVerbose';
+
+export * from './types';
diff --git a/packages/superset-ui-time-format/src/types.ts b/packages/superset-ui-time-format/src/types.ts
index 21f36481df..44ed03ee3b 100644
--- a/packages/superset-ui-time-format/src/types.ts
+++ b/packages/superset-ui-time-format/src/types.ts
@@ -1 +1,20 @@
export type TimeFormatFunction = (value: Date) => string;
+
+export type TimeGranularity =
+ | 'date'
+ | 'PT1S'
+ | 'PT1M'
+ | 'PT5M'
+ | 'PT10M'
+ | 'PT15M'
+ | 'PT0.5H'
+ | 'PT1H'
+ | 'P1D'
+ | 'P1W'
+ | 'P1M'
+ | 'P0.25Y'
+ | 'P1Y'
+ | '1969-12-28T00:00:00Z/P1W'
+ | '1969-12-29T00:00:00Z/P1W'
+ | 'P1W/1970-01-03T00:00:00Z'
+ | 'P1W/1970-01-04T00:00:00Z';
diff --git a/packages/superset-ui-time-format/test/factories/getTimeFormatterForGranularity.test.ts b/packages/superset-ui-time-format/test/factories/getTimeFormatterForGranularity.test.ts
new file mode 100644
index 0000000000..cc3c7d9ecc
--- /dev/null
+++ b/packages/superset-ui-time-format/test/factories/getTimeFormatterForGranularity.test.ts
@@ -0,0 +1,34 @@
+import getFormatter from '../../src/factories/getTimeFormatterForGranularity';
+import smartDateVerbose from '../../src/formatters/smartDateVerbose';
+
+describe('getTimeFormatterForGranularity()', () => {
+ it('use smartDate when granularity unknown or undefined', () => {
+ expect(getFormatter(undefined)).toBe(smartDateVerbose);
+ // @ts-ignore
+ expect(getFormatter('random-string')).toBe(smartDateVerbose);
+ });
+
+ it('format time for known granularities', () => {
+ // JS Date constructor month is zero-based
+ const date = new Date(2020, 4, 10, 11, 10, 1); // May 10, 2020 is Sunday
+ expect(getFormatter('date')(date)).toBe('2020-05-10');
+ expect(getFormatter('PT1S')(date)).toBe('2020-05-10 11:10:01');
+ expect(getFormatter('PT1M')(date)).toBe('2020-05-10 11:10');
+ expect(getFormatter('PT5M')(date)).toBe('2020-05-10 11:10');
+ expect(getFormatter('PT10M')(date)).toBe('2020-05-10 11:10');
+ expect(getFormatter('PT15M')(date)).toBe('2020-05-10 11:10');
+ expect(getFormatter('PT0.5H')(date)).toBe('2020-05-10 11:10');
+ expect(getFormatter('PT1H')(date)).toBe('2020-05-10 11:00');
+ expect(getFormatter('P1D')(date)).toBe('2020-05-10');
+ expect(getFormatter('P1W')(date)).toBe('2020-05-10 W19');
+ expect(getFormatter('P1M')(date)).toBe('2020-05');
+ expect(getFormatter('P0.25Y')(date)).toBe('2020 Q2');
+ expect(getFormatter('P1Y')(date)).toBe('2020');
+ // sunday based week
+ expect(getFormatter('1969-12-28T00:00:00Z/P1W')(date)).toBe('2020-05-10 W19');
+ expect(getFormatter('P1W/1970-01-03T00:00:00Z')(date)).toBe('2020-05-10 W19');
+ // monday based week
+ expect(getFormatter('1969-12-29T00:00:00Z/P1W')(date)).toBe('2020-05-10 W18');
+ expect(getFormatter('P1W/1970-01-04T00:00:00Z')(date)).toBe('2020-05-10 W18');
+ });
+});
diff --git a/plugins/legacy-preset-chart-big-number/src/BigNumber/transformProps.ts b/plugins/legacy-preset-chart-big-number/src/BigNumber/transformProps.ts
index 7b9526a17e..d08a0984d7 100644
--- a/plugins/legacy-preset-chart-big-number/src/BigNumber/transformProps.ts
+++ b/plugins/legacy-preset-chart-big-number/src/BigNumber/transformProps.ts
@@ -19,9 +19,7 @@
import * as color from 'd3-color';
import { getNumberFormatter, NumberFormats } from '@superset-ui/number-format';
import { ChartProps } from '@superset-ui/chart';
-import getTimeFormatterForGranularity, {
- TimeGranularity,
-} from '../utils/getTimeFormatterForGranularity';
+import { TimeGranularity, getTimeFormatterForGranularity } from '@superset-ui/time-format';
const TIME_COLUMN = '__timestamp';
const formatPercentChange = getNumberFormatter(NumberFormats.PERCENT_SIGNED_1_POINT);
diff --git a/plugins/legacy-preset-chart-big-number/test/transformProps.test.ts b/plugins/legacy-preset-chart-big-number/test/transformProps.test.ts
index 38aa572d3d..13b234a550 100644
--- a/plugins/legacy-preset-chart-big-number/test/transformProps.test.ts
+++ b/plugins/legacy-preset-chart-big-number/test/transformProps.test.ts
@@ -17,11 +17,11 @@
* under the License.
*/
import { DatasourceType } from '@superset-ui/query';
+import { TimeGranularity } from '@superset-ui/time-format';
import transformProps, {
BignumberChartProps,
BigNumberDatum,
} from '../src/BigNumber/transformProps';
-import { TimeGranularity } from '../src/utils/getTimeFormatterForGranularity';
const formData = {
metric: 'value',