From 881a848c930aa2b72d8eb24098385d024295fd76 Mon Sep 17 00:00:00 2001 From: SheetJS Date: Fri, 23 Jun 2023 16:24:44 -0400 Subject: [PATCH] 0.20.0 --- docz/docs/03-demos/08-local/01-file.md | 2 +- docz/docs/03-demos/12-engines/08_quickjs.md | 6 +- docz/docs/07-csf/07-features/03-dates.md | 291 ++++++++++++++++++-- docz/docs/08-api/03-parse-options.md | 4 + docz/docs/08-api/05-write-options.md | 4 + docz/docs/08-api/07-utilities/01-array.md | 15 + docz/docs/08-api/07-utilities/05-html.md | 6 + docz/package.json | 2 +- docz/static/DateTime.xlsx | Bin 0 -> 9333 bytes docz/version.js | 2 +- 10 files changed, 310 insertions(+), 22 deletions(-) create mode 100644 docz/static/DateTime.xlsx diff --git a/docz/docs/03-demos/08-local/01-file.md b/docz/docs/03-demos/08-local/01-file.md index 118b65f..576dfab 100644 --- a/docz/docs/03-demos/08-local/01-file.md +++ b/docz/docs/03-demos/08-local/01-file.md @@ -143,7 +143,7 @@ const u8 = XLSX.write(wb, { bookType: "xlsx", type: "buffer" }); /* create Blob */ const blob = new Blob([u8]); /* create object URL */ -const url = URL.createObjectURL(new Blob([u8])); +const url = URL.createObjectURL(blob); /* create `A` DOM element */ const a = document.createElement("a"); diff --git a/docz/docs/03-demos/12-engines/08_quickjs.md b/docz/docs/03-demos/12-engines/08_quickjs.md index 75240cb..41e590a 100644 --- a/docz/docs/03-demos/12-engines/08_quickjs.md +++ b/docz/docs/03-demos/12-engines/08_quickjs.md @@ -29,7 +29,7 @@ command-line tool for reading data from files. :::note Many QuickJS functions are not documented. The explanation was verified against -the latest release (version `2021-03-27`, commit `2788d71`). +the latest release (commit `2788d71`). ::: @@ -268,7 +268,7 @@ This demo was tested in the following deployments: | `darwin-arm` | `2788d71` | 2023-06-05 | | `linux-x64` | `2788d71` | 2023-06-02 | -Git commit `2788d71` corresponds to the latest release (`2021-03-27`) +When the demo was tested, commit `2788d71` corresponded to the latest release. ::: @@ -329,7 +329,7 @@ first worksheet name, and the contents of the first sheet as CSV rows. :::note -This demo was last tested on 2023 March 11 against QuickJS `2021-03-27`. +This demo was last tested on 2023 March 11 against QuickJS commit `2788d71`. ::: diff --git a/docz/docs/07-csf/07-features/03-dates.md b/docz/docs/07-csf/07-features/03-dates.md index 5b4cbe7..7ecbadc 100644 --- a/docz/docs/07-csf/07-features/03-dates.md +++ b/docz/docs/07-csf/07-features/03-dates.md @@ -4,6 +4,55 @@ sidebar_position: 3 # Dates and Times +
+ File Format Support (click to show) + +Dates are a core concept in nearly every spreadsheet application in existence. +Some legacy spreadsheet apps only supported dates. Others supported times as a +distinct concept from dates. + +Some file formats store dates in a textual format, while others store dates with +[numbers representing a difference from an epoch](#relative-epochs). + +Many spreadsheet apps use special number formats to signal that values are dates +or times. Quattro Pro for DOS had a distinct set of Date number formats and +Time number formats, but did not have a mixed Date + Time format. + +Lotus 1-2-3 used a ["1900" date system](#1904-and-1900-date-systems), while +Numbers exclusively supports 1904 under the hood. Excel file formats typically +include options for specifying the date system + +| Formats | Date | Time | D+T | Date Storage | Date System | +|:------------------|:----:|:----:|:---:|:--------------------:|:------------| +| NUMBERS | ✔ | ✔ | ✔ | Number | 1904 Only | +| XLSX / XLSM | ✔ | ✔ | ✔ | Number | 1900 + 1904 | +| XLSX (Strict ISO) | ✔ | ✔ | ✔ | Relative Date | 1900 + 1904 | +| XLSB | ✔ | ✔ | ✔ | Number | 1900 + 1904 | +| XLML | ✔ | ✔ | ✔ | Relative Date | 1900 + 1904 | +| XLS (BIFF5/8) | ✔ | ✔ | ✔ | Relative Date | 1900 + 1904 | +| XLS (BIFF2/3/4) | ✔ | ✔ | ✔ | Relative Date | 1900 + 1904 | +| XLR (Works) | ✔ | ✔ | ✔ | Relative Date | 1900 + 1904 | +| ET (WPS 电子表格) | ✔ | ✔ | ✔ | Relative Date | 1900 + 1904 | +| ODS / FODS / UOS | ✔ | ✔ | ✔ | ISO Duration or Date | Arbitrary | +| HTML | ✔ | ✔ | ✔ | Plaintext | Calendar | +| CSV / TSV / Text | ✔ | ✔ | ✔ | Plaintext | Calendar | +| DBF | ✔ | * | * | Number or Plaintext | Calendar | +| DIF | ✔ | ✔ | ✔ | Plaintext | Calendar | +| WK1 | ✔ | ✔ | ✕ | Number | 1900 | +| WKS (Works) | ✔ | ✔ | ✕ | Number | 1900 | +| WQ1 | ✔ | | ✕ | Number | 1900 | +| QPW | ✔ | ✔ | * | Number | 1900 | + +X (✕) marks features that are not supported by the file formats. For example, +the WK1 file format had date-only formats and time-only formats but no mixed +date-time formats. + +Newer DBF levels support a special `T` field type that represents date + time. + +The QPW file format supports mixed date + time formats in custom number formats. + +
+ Lotus 1-2-3, Excel, and other spreadsheet software do not have a true concept of date or time. Instead, dates and times are stored as offsets from an epoch. The magic behind date interpretations is hidden in functions or number formats. @@ -11,6 +60,44 @@ The magic behind date interpretations is hidden in functions or number formats. SheetJS attempts to create a friendly JS date experience while also exposing options to use the traditional date codes +:::tip pass + +Date and time handling was overhauled in version `0.20.0`. It is strongly +recommended to [upgrade](/docs/getting-started/installation/). + +::: + +The following example exports the current time to XLSX spreadsheet. The time +shown on this page will be the time displayed in Excel + +```jsx live +function SheetJSNow() { + const [date, setDate] = React.useState(new Date()); + const xport = React.useCallback(() => { + /* generate array of arrays */ + const aoa = [[date]]; + /* to avoid confusion, set milliseconds to 0 */ + aoa[0][0].setMilliseconds(0); + /* generate workbook */ + const ws = XLSX.utils.aoa_to_sheet(aoa, {dense: true}); + /* set cell A1 number format */ + ws["!data"][0][0].z = "yyyy-mm-dd hh:mm:ss" + ws["!cols"] = [{wch: 20}]; + + /* generate workbook and export */ + const wb = XLSX.utils.book_new(); + XLSX.utils.book_append_sheet(wb, ws, "Sheet1"); + XLSX.writeFile(wb, "SheetJSNow.xlsx"); + }, []); + return ( <> +

+ Local Time:{date.toString()} + +

+ + ) +} +``` ## How Spreadsheets Understand Time @@ -38,7 +125,7 @@ the date code. The following table covers some common formats: -
Common Date-Time Formats (click to hide) +
Common Date-Time Formats (click to show) | Fragment | Interpretation | |:---------|:-----------------------------| @@ -134,11 +221,6 @@ JavaScript Date objects are timezone-aware) This is a deficiency of the spreadsheet software. Excel has no native concept of universal time. -The library attempts to normalize the dates. All times are specified in the -local time zone. SheetJS cannot magically fix the technical problems with -Excel and other spreadsheet software, but this represents . - - ## How Files Store Dates and Times XLS, XLSB, and most binary formats store the raw date codes. Special number @@ -155,27 +237,173 @@ support is poor. ODS does support absolute time values but drops the actual timezone indicator when parsing. In that sense, LibreOffice follows the same behavior as Excel. +Numbers uses a calendar date system, but records pure time values as if they are +absolute times in 1904 January 01. It is spiritually equivalent to the 1904 mode +in Excel and other spreadsheet applications. + +## How JavaScript Engines Understand Time + +JavaScript provides a `Date` object which represents an *absolute* time. Under +the hood, `Date` uses the "UNIX" epoch of 1970 January 01 midnight in UTC. This +means the actual zero date is different in different timezones! + +| Location | IANA Timezone | `new Date(0)` in local time | +|:------------|:----------------------|:----------------------------| +| Honolulu | `Pacific/Honolulu` | `1969-12-31 02:00 PM` | +| Los Angeles | `America/Los_Angeles` | `1969-12-31 04:00 PM` | +| New York | `America/New_York` | `1969-12-31 07:00 PM` | +| Sao Paulo | `America/Sao_Paulo` | `1969-12-31 09:00 PM` | +| London | `Europe/London` | `1970-01-01 01:00 AM` | +| Cairo | `Africa/Cairo` | `1970-01-01 02:00 AM` | +| Djibouti | `Africa/Djibouti` | `1970-01-01 03:00 AM` | +| Chennai | `Asia/Kolkata` | `1970-01-01 05:30 AM` | +| Shanghai | `Asia/Shanghai` | `1970-01-01 08:00 AM` | +| Seoul | `Asia/Seoul` | `1970-01-01 09:00 AM` | +| Sydney | `Australia/Sydney` | `1970-01-01 10:00 AM` | + +In modern environments, the IANA Timezone and timezone offset can be discovered +through the `Intl` and `Date` objects: + +```jsx live +function LocalInfo() { + const date = new Date(); + return ( <> + Local Time: {date.toString()}
+ Time offset (relative to UTC): {-date.getTimezoneOffset()/60} hours
+ IANA Timezone: {Intl.DateTimeFormat().resolvedOptions().timeZone} +)} +``` + +:::caution + +The timezone information is provided by the JavaScript engine and local settings. +There are outstanding Google Chrome and V8 bugs related to rounded offsets for +timezones under a lunar calendar. The last timezone to switch to the Gregorian +calendar was `Africa/Monrovia` (in 1972). + +SheetJS utilities attempt to work around the browser bugs. + +::: + +### UTC and Local Time + +The `Date` object has a number of prototype methods for inspecting the object. +Some methods interact with the true value, while others convert to the local +timezone. Some methods are listed in the table below: + +| Feature | Local Time method | UTC method | +|:-----------------|:------------------|:-----------------| +| Year | `getFullYear` | `getUTCFullYear` | +| Month (0-11) | `getMonth` | `getUTCMonth` | +| Day of the month | `getDate` | `getUTCDate` | +| Hours | `getHours` | `getUTCHours` | +| Minutes | `getMinutes` | `getUTCMinutes` | +| Seconds | `getSeconds` | `getUTCSeconds` | +| Entire date | `toString` | `toUTCString` | + +It is typical for websites and other applications to present data in local time. +To serve an international audience, backend servers typically use UTC time. + +The following example shows the time when the page was loaded. The same absolute +time will appear to be different under local and UTC interpretations: + +```jsx live +function LocalUTC() { + const d = new Date(); + /* display number with 2 digits, prepending `0` if necessary */ + const f = (n) => n.toString().padStart(2, "0"); + /* HH:MM:SS using local interpretation */ + const local = `${f(d.getHours())}:${f(d.getMinutes())}:${f(d.getSeconds())}`; + /* HH:MM:SS using UTC interpretation */ + const utc = `${f(d.getUTCHours())}:${f(d.getUTCMinutes())}:${f(d.getUTCSeconds())}`; + return ( <> + Local Interpretation
+ toString: {d.toString()}
+ 24-hour time: {local}
+
+ UTC Interpretation
+ toUTCString: {d.toUTCString()}
+ 24-hour time: {utc}
+)} +``` ## How SheetJS handles Dates and Times -The default behavior for all parsers is to generate number cells. Passing the -`cellDates` to true will force the parsers to store dates: +SheetJS attempts to reconcile the spreadsheet and JavaScript date concepts. -```js -// cell A1 will be { t: 'n', v: 54337 } -var wb_sans_date = XLSX.read("10/6/2048", {type:"binary"}); +The default behavior for all parsers is to generate number cells. Setting +`cellDates` to true will force the parsers to store dates. -// cell A1 will be { t: 'd', v: } -var wb_with_date = XLSX.read("10/6/2048", {type:"binary", cellDates: true}); +```jsx live +function SheetJSCellDates() { + var csv = "Date,10/6/2048"; + + // cell B1 will be { t: 'n', v: 54337 } + var wb_sans_date = XLSX.read(csv, {type:"binary"}); + var ws_sans_date = wb_sans_date.Sheets.Sheet1; + + // cell B1 will be { t: 'd', v: } + var wb_with_date = XLSX.read(csv, {type:"binary", cellDates: true}); + var ws_with_date = wb_with_date.Sheets.Sheet1; + + return (<> + CSV:
{csv}
+ Cell B1:

+ + + + + + + + + +
cellDatestypevalue
(unspecified){ws_sans_date["B1"].t}{ws_sans_date["B1"].v}
true{ws_with_date["B1"].t}{ws_with_date["B1"].v.toISOString()} (Date object)
+ ); +} ``` When writing, date cells are automatically translated back to numeric cells with an appropriate number format. -The actual values stored in cells are intended to be correct from the -perspective of an Excel user in the current timezone. - The value formatting logic understands date formats and converts when relevant. +It always uses the UTC interpretation of Date objects. + +### Date Objects + +The actual values stored in cells are intended to be correct when interpreted +using UTC date methods. + +For example, [`DateTime.xlsx`](pathname:///DateTime.xlsx) is a test file with the following data: + +| Type | Value | +|:---------|----------------------:| +| Date | `2048-10-06` | +| Time | `15:00` | +| DateTime | `2048-10-06 15:00:00` | + +The raw data values are shown in the live demo. The UTC date string will show +the same value as Excel irrespective of the local timezone. + +```jsx live +function SheetJSDateTimeXlsxValues() { + const [data, setData] = React.useState([[]]); + React.useEffect(() => { (async() => { + const ab = await (await fetch("/DateTime.xlsx")).arrayBuffer(); + const wb = XLSX.read(ab, {cellDates: true, dense: true}); + setData(wb.Sheets.Sheet1["!data"]); + })(); }); + return ( + + + {data.slice(1).map((row,R) => ( + + + + ))} +
Excel DateUTC DateLocal Date
{row[1].w}{row[1].v.toUTCString()}{row[1].v.toString()}
); +} +``` ### Utility Functions @@ -206,6 +434,37 @@ var ws = XLSX.utils.aoa_to_sheet([[new Date()]], { cellDates: true }); var A1 = XLSX.utils.sheet_to_json(ws, { header: 1 })[0][0]; ``` +### UTC Option + +Some API functions support the `UTC` option to control how dates are handled. + +**[`sheet_to_json`](/docs/api/utilities/array#array-output)** + +If `UTC` is true, the dates will be correct when interpreted in UTC. By default, +the dates will be correct when interpreted in local time. + +Typically `UTC` is used for data from an API endpoint, as servers typically emit +UTC dates and expect scripts to localize. The local interpretation is sensible +when users submit data, as they will be providing times in their local timezone. + +**[`aoa_to_sheet` / `sheet_add_aoa`](/docs/api/utilities/array#array-of-arrays-input)** / **[`json_to_sheet` / `sheet_add_json`](/docs/api/utilities/array#array-of-objects-input)** + +If `UTC` is true, the UTC interpretation of dates will be used. + +Typically `UTC` is used for data from an API endpoint, as servers typically emit +UTC dates and expect scripts to localize. The local interpretation is sensible +when date objects are generated in the browser. + + +**[`table_to_book` / `table_to_sheet` / `sheet_add_dom`](/docs/api/utilities/html#html-table-input)** + +If `UTC` is true, potential dates are interpreted as if they represent UTC times. +By default, potential dates are interpreted in local time. + +Typically `UTC` is used for data exported from Excel or other spreadsheet apps. +If the table is programmatically generated in the frontend, the dates and times +will be in the local timezone and the local interpretation is preferable. + ### Number Formats By default, the number formats are not emitted. For Excel-based file formats, diff --git a/docz/docs/08-api/03-parse-options.md b/docz/docs/08-api/03-parse-options.md index 3935894..96ec3f2 100644 --- a/docz/docs/08-api/03-parse-options.md +++ b/docz/docs/08-api/03-parse-options.md @@ -38,6 +38,7 @@ The read functions accept an options argument: |`PRN` | false | If true, allow parsing of PRN files ** | |`xlfn` | false | If true, preserve `_xlfn.` prefixes in formulae ** | |`FS` | | DSV Field Separator override | +|`UTC` | true | If explicitly false, parse text dates in local time | - Even if `cellNF` is false, formatted text will be generated and saved to `.w` - In some cases, sheets may be parsed even if `bookSheets` is false. @@ -72,6 +73,9 @@ The read functions accept an options argument: - By default, "sparse" mode worksheets are generated. Individual cells are accessed by indexing the worksheet object with an A1-Style address. "dense" worksheets store cells in an array of arrays at `sheet["!data"]`. +- `UTC` applies to CSV, Text and HTML formats. When explicitly set to `false`, + the parsers will assume the files are specified in local time. By default, as + is the case for other file formats, dates and times are interpreted in UTC. ### Input Type diff --git a/docz/docs/08-api/05-write-options.md b/docz/docs/08-api/05-write-options.md index 5b60001..8867747 100644 --- a/docz/docs/08-api/05-write-options.md +++ b/docz/docs/08-api/05-write-options.md @@ -85,6 +85,8 @@ The write functions accept an options argument: |`themeXLSX` | | Override theme XML when writing XLSX/XLSB/XLSM ** | |`ignoreEC` | `true` | Suppress "number as text" errors ** | |`numbers` | | Payload for NUMBERS export ** | +|`FS` | `","` | "Field Separator" delimiter between fields ** | +|`RS` | `"\n"` | "Record Separator" delimiter between rows ** | - `bookSST` is slower and more memory intensive, but has better compatibility with older versions of iOS Numbers @@ -102,6 +104,8 @@ The write functions accept an options argument: - Due to a bug in the program, some features like "Text to Columns" will crash Excel on worksheets where error conditions are ignored. The writer will mark files to ignore the error by default. Set `ignoreEC` to `false` to suppress. +- `FS` and `RS` apply to CSV and Text output formats. The options are discussed + in ["CSV and Text"](/docs/api/utilities/csv#delimiter-separated-output)
Exporting NUMBERS files (click to show) diff --git a/docz/docs/08-api/07-utilities/01-array.md b/docz/docs/08-api/07-utilities/01-array.md index 49e3ebe..f2c5036 100644 --- a/docz/docs/08-api/07-utilities/01-array.md +++ b/docz/docs/08-api/07-utilities/01-array.md @@ -140,6 +140,9 @@ The function takes an options argument: |`cellDates` | false | Store dates as type `d` (default is `n`) | |`sheetStubs` | false | Create cell objects of type `z` for `null` values | |`nullError` | false | If true, emit `#NULL!` error cells for `null` values | +|`UTC` | false | If true, dates are interpreted using UTC methods ** | + +[UTC option is explained in "Dates"](/docs/csf/features/dates#utc-option) The following live example reproduces the [example worksheet](#example-sheet): @@ -181,6 +184,9 @@ accepts an options argument: |`sheetStubs` | false | Create cell objects of type `z` for `null` values | |`nullError` | false | If true, emit `#NULL!` error cells for `null` values | |`origin` | | Use specified cell as starting point (see below) | +|`UTC` | false | If true, dates are interpreted using UTC methods ** | + +[UTC option is explained in "Dates"](/docs/csf/features/dates#utc-option) `origin` is expected to be one of: @@ -272,6 +278,9 @@ default column order is determined by the first appearance of the field using |`cellDates` | false | Store dates as type `d` (default is `n`) | |`skipHeader` | false | If true, do not include header row in output | |`nullError` | false | If true, emit `#NULL!` error cells for `null` values | +|`UTC` | false | If true, dates are interpreted using UTC methods ** | + +[UTC option is explained in "Dates"](/docs/csf/features/dates#utc-option) :::caution @@ -381,6 +390,9 @@ an options argument: |`skipHeader` | false | If true, do not include header row in output | |`nullError` | false | If true, emit `#NULL!` error cells for `null` values | |`origin` | | Use specified cell as starting point (see below) | +|`UTC` | false | If true, dates are interpreted using UTC methods ** | + +[UTC option is explained in "Dates"](/docs/csf/features/dates#utc-option) `origin` is expected to be one of: @@ -512,6 +524,7 @@ an options argument: |`dateNF` | FMT 14 | Use specified date format in string output | |`defval` | | Use specified value in place of null or undefined | |`blankrows` | ** | Include blank lines in the output ** | +|`UTC` | false | If true, dates will be correct in UTC ** | - `raw` only affects cells which have a format code (`.z`) field or a formatted text (`.w`) field. @@ -527,6 +540,8 @@ an options argument: be set to `false` to skip blank rows. - When `header` is not `1`, the default is to skip blank rows. `blankrows` must be true to generate blank rows +- [UTC option is explained in "Dates"](/docs/csf/features/dates#utc-option) + `range` is expected to be one of: diff --git a/docz/docs/08-api/07-utilities/05-html.md b/docz/docs/08-api/07-utilities/05-html.md index 4632967..41ba81f 100644 --- a/docz/docs/08-api/07-utilities/05-html.md +++ b/docz/docs/08-api/07-utilities/05-html.md @@ -97,6 +97,9 @@ Both functions accept options arguments: |`cellDates` | false | Store dates as type `d` (default is `n`) | |`sheetRows` | 0 | If >0, read the first `sheetRows` rows of the table | |`display` | false | If true, hidden rows and cells will not be parsed | +|`UTC` | false | If true, dates are interpreted as UTC ** | + +[UTC option is explained in "Dates"](/docs/csf/features/dates#utc-option) Exporting a table to a spreadsheet file in the web browser involves 3 steps: "find the table", "generate a workbook object", and "export to file". @@ -165,6 +168,9 @@ an options argument: |`cellDates` | false | Store dates as type `d` (default is `n`) | |`sheetRows` | 0 | If >0, read the first `sheetRows` rows of the table | |`display` | false | If true, hidden rows and cells will not be parsed | +|`UTC` | false | If true, dates are interpreted as UTC ** | + +[UTC option is explained in "Dates"](/docs/csf/features/dates#utc-option) `origin` is expected to be one of: diff --git a/docz/package.json b/docz/package.json index f339b2d..a8854ae 100644 --- a/docz/package.json +++ b/docz/package.json @@ -26,7 +26,7 @@ "prism-react-renderer": "1.3.5", "react": "17.0.2", "react-dom": "17.0.2", - "xlsx": "https://cdn.sheetjs.com/xlsx-0.19.3/xlsx-0.19.3.tgz" + "xlsx": "https://cdn.sheetjs.com/xlsx-0.20.0/xlsx-0.20.0.tgz" }, "devDependencies": { "@docusaurus/module-type-aliases": "2.4.1" diff --git a/docz/static/DateTime.xlsx b/docz/static/DateTime.xlsx new file mode 100644 index 0000000000000000000000000000000000000000..f34967ad65692ac08a23f20acbfcc5ff2e123337 GIT binary patch literal 9333 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 NIp|yvPVw;W{{ZO+2n7HD literal 0 HcmV?d00001 diff --git a/docz/version.js b/docz/version.js index c5b13f7..8d6c147 100644 --- a/docz/version.js +++ b/docz/version.js @@ -1,3 +1,3 @@ -//const version = "0.19.3"; +//const version = "0.20.0"; import { version } from "xlsx"; export default version;