Skip to content

Commit

Permalink
Provide datetime values with a timezone offset specified. Render diff…
Browse files Browse the repository at this point in the history
…erently
  • Loading branch information
garrettmflynn committed Jun 3, 2024
1 parent ad1cf97 commit 303e275
Show file tree
Hide file tree
Showing 3 changed files with 72 additions and 37 deletions.
88 changes: 61 additions & 27 deletions src/electron/frontend/core/components/DateTimeSelector.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,38 @@
import { LitElement, css } from "lit";

const convertToDateTimeLocalString = (date) => {
export function extractISOString(date, {
// timezone = false,
offset = false,
} = {}) {

// Function to format the GMT offset
function formatOffset(date) {
let offset = -date.getTimezoneOffset(); // getTimezoneOffset returns the difference in minutes from UTC
const sign = offset >= 0 ? "+" : "-";
offset = Math.abs(offset);
const hours = String(Math.floor(offset / 60)).padStart(2, '0');
const minutes = String(offset % 60).padStart(2, '0');
return `${sign}${hours}:${minutes}`;
}

// Extract the GMT offset
const gmtOffset = formatOffset(date);

// Format the date back to the original format with GMT offset
const year = date.getFullYear();
const month = (date.getMonth() + 1).toString().padStart(2, "0");
const day = date.getDate().toString().padStart(2, "0");
const hours = date.getHours().toString().padStart(2, "0");
const minutes = date.getMinutes().toString().padStart(2, "0");
return `${year}-${month}-${day}T${hours}:${minutes}`;
};
const month = String(date.getMonth() + 1).padStart(2, '0'); // Months are zero-indexed
const day = String(date.getDate()).padStart(2, '0');
const hours = String(date.getHours()).padStart(2, '0');
const minutes = String(date.getMinutes()).padStart(2, '0');
const seconds = String(date.getSeconds()).padStart(2, '0');

// Recreate the ISO string with the GMT offset
let formattedDate = `${year}-${month}-${day}T${hours}:${minutes}:${seconds}`;
if (offset) formattedDate += gmtOffset;

return formattedDate;
}


export class DateTimeSelector extends LitElement {
static get styles() {
Expand All @@ -19,47 +44,52 @@ export class DateTimeSelector extends LitElement {
`;
}


// Manually handle value property
get value() {
return this.input.value;
const date = new Date(this.input.value);
return extractISOString(date, { offset: true });
}


// Render the date without timezone offset
set value(newValue) {
if (newValue) this.input.value = newValue;

if (newValue) this.input.value = extractISOString(new Date(newValue));

else {
const d = new Date();
d.setHours(0, 0, 0, 0);
this.input.value = convertToDateTimeLocalString(d);
this.input.value = extractISOString(d);
}
}
get min() {
return this.input.min;
}

set min(newValue) {
this.input.min = newValue;
static get properties() {
return {
min: { type: String, reflect: true },
max: { type: String, reflect: true },
timezone: { type: String, reflect: true },
};
}

get max() {
return this.input.max;
}

set max(newValue) {
this.input.max = newValue;
}

constructor({ value, min, max } = {}) {
constructor({
value,
min,
max,
} = {}) {
super();
this.input = document.createElement("input");
this.input.type = "datetime-local";
this.input.min = min;
this.input.max = max;

this.min = min;
this.max = max;

this.addEventListener("click", () => {
this.input.focus();
this.input.showPicker();
});

this.value = value ? convertToDateTimeLocalString(value) : value;
this.value = value;
}

focus() {
Expand All @@ -71,6 +101,10 @@ export class DateTimeSelector extends LitElement {
}

render() {

this.input.min = min;
this.input.max = max;

return this.input;
}
}
Expand Down
19 changes: 10 additions & 9 deletions src/electron/frontend/core/components/JSONSchemaInput.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,18 +16,17 @@ import tippy from "tippy.js";
import { merge } from "./pages/utils";
import { OptionalSection } from "./OptionalSection";
import { InspectorListItem } from "./preview/inspector/InspectorList";
import { extractISOString } from "./DateTimeSelector";

const isDevelopment = !!import.meta.env;

const dateTimeRegex = /(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2})/;

function resolveDateTime(value) {
if (typeof value === "string") {
const match = value.match(dateTimeRegex);
if (match) return `${match[1]}-${match[2]}-${match[3]}T${match[4]}:${match[5]}`;
return value;
}
if (typeof value === "string") return extractISOString(new Date(value), { offset: true })
return value;
}

function renderDateTime(value) {
if (typeof value === "string") return extractISOString(new Date(value));
return value;
}

Expand Down Expand Up @@ -1226,7 +1225,7 @@ export class JSONSchemaInput extends LitElement {
? "datetime-local"
: schema.format ?? (schema.type === "string" ? "text" : schema.type);

const value = isDateTime ? resolveDateTime(this.value) : this.value;
const value = isDateTime ? renderDateTime(this.value) : this.value;

const { minimum, maximum, exclusiveMax, exclusiveMin } = schema;
const min = exclusiveMin ?? minimum;
Expand All @@ -1242,13 +1241,15 @@ export class JSONSchemaInput extends LitElement {
.min="${min}"
.max="${max}"
@input=${(ev) => {
let value = ev.target.value;
let newValue = value;
// const isBlank = value === '';
if (isInteger) value = newValue = parseInt(value);
else if (isNumber) value = newValue = parseFloat(value);
else if (isDateTime) value = newValue = resolveDateTime(value)
if (isNumber) {
if ("min" in schema && newValue < schema.min) newValue = schema.min;
Expand All @@ -1274,7 +1275,7 @@ export class JSONSchemaInput extends LitElement {
const nanHandler = ev.target.parentNode.querySelector(".nan-handler");
if (!(newValue && Number.isNaN(newValue))) nanHandler.checked = false;
}
this.#updateData(fullPath, value);
}}
@change=${(ev) => validateOnChange && this.#triggerValidation(name, path)}
Expand Down
2 changes: 1 addition & 1 deletion src/schemas/base-metadata.schema.ts
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,7 @@ export const preprocessMetadataSchema = (schema: any = baseMetadataSchema, globa
copy.order = [ "NWBFile", "Subject" ]

const minDate = "1900-01-01T00:00"
const maxDate = getISODateInTimezone().slice(0, -2)
const maxDate = getISODateInTimezone().slice(0, -2) // Restrict date to current date with timezone awareness


// Add unit to weight
Expand Down

0 comments on commit 303e275

Please sign in to comment.