mirror of
https://github.com/gristlabs/grist-core.git
synced 2026-03-02 04:09:24 +00:00
(core) Fuller guessing of type and options when adding first data to blank columns
Summary: Adds `common/ValueGuesser.ts` with logic for guessing column type and widget options (only for dates/datetimes) from an array of strings, and converting the strings to the guessed type in a lossless manner, so that converting back to Text gives the original values. Changes `_ensure_column_accepts_data` in Python to call an exported JS method using the new logic where possible. Test Plan: Added `test/common/ValueGuesser.ts` to unit test the core guessing logic and a DocApi end-to-end test for what happens to new columns. Reviewers: georgegevoian Reviewed By: georgegevoian Differential Revision: https://phab.getgrist.com/D3290
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
import escapeRegExp = require('lodash/escapeRegExp');
|
||||
import memoize = require('lodash/memoize');
|
||||
import {getDistinctValues} from 'app/common/gutil';
|
||||
import {getDistinctValues, isObject} from 'app/common/gutil';
|
||||
// Simply importing 'moment-guess' inconsistently imports bundle.js or bundle.esm.js depending on environment
|
||||
import * as guessFormat from '@gristlabs/moment-guess/dist/bundle.js';
|
||||
import * as moment from 'moment-timezone';
|
||||
@@ -325,8 +325,9 @@ function standardizeTime(timeString: string): { remaining: string, time: string
|
||||
return {remaining: timeString.slice(0, match.index).trim(), time: `${hh}:${mm}:${ss}`};
|
||||
}
|
||||
|
||||
export function guessDateFormat(values: string[], timezone: string = 'UTC'): string | null {
|
||||
const sample = getDistinctValues(values, 100);
|
||||
export function guessDateFormat(values: Array<string | null>, timezone: string = 'UTC'): string | null {
|
||||
const dateStrings: string[] = values.filter(isObject);
|
||||
const sample = getDistinctValues(dateStrings, 100);
|
||||
const formats: Record<string, number> = {};
|
||||
for (const dateString of sample) {
|
||||
let guessed: string | string[];
|
||||
@@ -348,7 +349,7 @@ export function guessDateFormat(values: string[], timezone: string = 'UTC'): str
|
||||
}
|
||||
|
||||
for (const format of formatKeys) {
|
||||
for (const dateString of values) {
|
||||
for (const dateString of dateStrings) {
|
||||
const m = moment.tz(dateString, format, true, timezone);
|
||||
if (m.isValid()) {
|
||||
formats[format] += 1;
|
||||
@@ -380,10 +381,15 @@ export const timeFormatOptions = [
|
||||
'HH:mm:ss z',
|
||||
];
|
||||
|
||||
export function dateTimeWidgetOptions(fullFormat: string) {
|
||||
/**
|
||||
* Construct widget options for a Date or DateTime column based on a single moment string
|
||||
* which may or may not contain both date and time parts.
|
||||
* If defaultTimeFormat is true, fallback to a non-empty default time format when none is found in fullFormat.
|
||||
*/
|
||||
export function dateTimeWidgetOptions(fullFormat: string, defaultTimeFormat: boolean) {
|
||||
const index = fullFormat.match(/[hHkaAmsSzZT]|$/)!.index!;
|
||||
const dateFormat = fullFormat.substr(0, index).trim();
|
||||
const timeFormat = fullFormat.substr(index).trim() || timeFormatOptions[0];
|
||||
const timeFormat = fullFormat.substr(index).trim() || (defaultTimeFormat ? timeFormatOptions[0] : "");
|
||||
return {
|
||||
dateFormat,
|
||||
timeFormat,
|
||||
|
||||
Reference in New Issue
Block a user