diff --git a/README.md b/README.md index d223435..81c5fb9 100644 --- a/README.md +++ b/README.md @@ -63,6 +63,12 @@ const options = { * defaults to false */ dotsForObjectNotation: false, + + /** + * display dates in local timezone, with the timezone offset displayed. + * otherwise, all dates will be converted to the UTC timezone + */ + dateWithTimezone: false, }; const formData = serialize( diff --git a/src/index.js b/src/index.js index 95ddbe3..c34f705 100644 --- a/src/index.js +++ b/src/index.js @@ -39,6 +39,15 @@ function isFile(value, isReactNative) { ); } +function toTzIsoString(date) { + const off = date.getTimezoneOffset(); + const absoff = Math.abs(off); + return (new Date(date.getTime() - off*60*1000).toISOString().substr(0,23) + + (off > 0 ? '-' : '+') + + Math.floor(absoff / 60).toFixed(0).padStart(2,'0') + ':' + + (absoff % 60).toString().padStart(2,'0')) +} + function initCfg(value) { return isUndefined(value) ? false : value; } @@ -53,6 +62,7 @@ function serialize(obj, cfg, fd, pre) { cfg.allowEmptyArrays = initCfg(cfg.allowEmptyArrays); cfg.noFilesWithArrayNotation = initCfg(cfg.noFilesWithArrayNotation); cfg.dotsForObjectNotation = initCfg(cfg.dotsForObjectNotation); + cfg.dateWithTimezone = initCfg(cfg.dateWithTimezone); const isReactNative = typeof fd.getParts === 'function'; @@ -83,7 +93,11 @@ function serialize(obj, cfg, fd, pre) { fd.append(pre + '[]', ''); } } else if (isDate(obj)) { - fd.append(pre, obj.toISOString()); + if (cfg.dateWithTimezone) { + fd.append(pre, toTzIsoString(obj)); + } else { + fd.append(pre, obj.toISOString()); + } } else if (isObject(obj) && !isBlob(obj, isReactNative)) { Object.keys(obj).forEach((prop) => { const value = obj[prop]; diff --git a/src/index.test.js b/src/index.test.js index 1304593..0ecce9c 100644 --- a/src/index.test.js +++ b/src/index.test.js @@ -291,6 +291,28 @@ test('Date', () => { expect(formData.get('foo')).toBe(foo.toISOString()); }); +test('Date with timezone', () => { + const toTzIsoString = (date) => { + const off = date.getTimezoneOffset(); + const absoff = Math.abs(off); + return (new Date(date.getTime() - off*60*1000).toISOString().substr(0,23) + + (off > 0 ? '-' : '+') + + Math.floor(absoff / 60).toFixed(0).padStart(2,'0') + ':' + + (absoff % 60).toString().padStart(2,'0')) + } + const foo = new Date(2000, 0, 1, 1, 1, 1); + const formData = serialize({ + foo, + }, + { + dateWithTimezone: true, + }); + + expect(formData.append).toHaveBeenCalledTimes(1); + expect(formData.append).toHaveBeenCalledWith('foo', toTzIsoString(foo)); + expect(formData.get('foo')).toBe(toTzIsoString(foo)); +}); + test('File', () => { const foo = new File([], ''); const formData = serialize({ diff --git a/types.d.ts b/types.d.ts index 88746cb..38e3102 100644 --- a/types.d.ts +++ b/types.d.ts @@ -5,6 +5,7 @@ export type Options = { allowEmptyArrays?: boolean; noFilesWithArrayNotation?: boolean; dotsForObjectNotation?: boolean; + dateWithTimezone?: boolean; }; export function serialize(