336 lines
10 KiB
JavaScript
336 lines
10 KiB
JavaScript
/* ZZeslint-disable */
|
|
//Browser Locale conversion utilities
|
|
|
|
import { faYinYang } from "@fortawesome/free-solid-svg-icons";
|
|
|
|
//dates,numbers currency etc
|
|
export default {
|
|
////////////////////////////////////////////////////////
|
|
// attempt to determine user's preferred language settings
|
|
// As of Jan 2020 all major browsers support
|
|
// navigator.languages
|
|
// but some use navigator.language (singular) to denote UI language preference
|
|
// not browsing language preference
|
|
// so the ideal way to do this is to use navigator.languages[0] for the preferred language
|
|
// and ignore the singular property since we don't care about the actual browser UI language
|
|
// only how the user expects to see the page itself
|
|
//
|
|
// also for sake of future proofing and edge cases need to have it be manually settable as well
|
|
// ############### TODO: modify all of these to put the user's manual override first in line (if there is one)
|
|
//https://appmakers.dev/bcp-47-language-codes-list/
|
|
getBrowserLanguages() {
|
|
return window.navigator.languages;
|
|
},
|
|
getBrowserFirstLanguage() {
|
|
return window.navigator.languages[0];
|
|
},
|
|
///////////////////////////////////////////
|
|
// Get users default time zone
|
|
// first check if overriden in useroptions
|
|
// if not then use browsers own setting
|
|
//https://www.iana.org/time-zones
|
|
//https://en.wikipedia.org/wiki/List_of_tz_database_time_zones
|
|
getResolvedTimeZoneName() {
|
|
let ov = window.$gz.store.state.userOptions.timeZoneOverride;
|
|
if (!window.$gz.util.stringIsNullOrEmpty(ov)) {
|
|
return window.$gz.store.state.userOptions.timeZoneOverride;
|
|
} else {
|
|
return Intl.DateTimeFormat().resolvedOptions().timeZone;
|
|
}
|
|
},
|
|
//////////////////////////////////////////////////
|
|
// Get the user's chosen currency name
|
|
//https://en.wikipedia.org/wiki/ISO_4217
|
|
getCurrencyName() {
|
|
return window.$gz.store.state.userOptions.currencyName;
|
|
},
|
|
//////////////////////////////////////////////////
|
|
// Get the user's chosen 12hr clock
|
|
//
|
|
getHour12() {
|
|
return window.$gz.store.state.userOptions.hour12;
|
|
},
|
|
///////////////////////////////////////////
|
|
// Turn a utc date into a displayable
|
|
// short date and time
|
|
// https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/toLocaleString
|
|
//
|
|
utcDateToShortDateAndTimeLocalized(
|
|
value,
|
|
timeZoneName,
|
|
languageName,
|
|
hour12
|
|
) {
|
|
if (!value) {
|
|
return "";
|
|
}
|
|
if (!timeZoneName) {
|
|
timeZoneName = this.getResolvedTimeZoneName();
|
|
}
|
|
if (!languageName) {
|
|
languageName = this.getBrowserLanguages();
|
|
}
|
|
|
|
if (!hour12) {
|
|
hour12 = this.getHour12();
|
|
}
|
|
|
|
//parse the date which is identified as utc ("2020-02-06T18:18:49.148011Z")
|
|
let parsedDate = new Date(value);
|
|
|
|
//is it a valid date?
|
|
if (!(parsedDate instanceof Date && !isNaN(parsedDate))) {
|
|
return "not valid";
|
|
}
|
|
|
|
return parsedDate.toLocaleString(languageName, {
|
|
timeZone: timeZoneName,
|
|
dateStyle: "short",
|
|
timeStyle: "short",
|
|
hour12: hour12
|
|
});
|
|
}, ///////////////////////////////////////////
|
|
// Turn a utc date into a displayable
|
|
// short date
|
|
//
|
|
utcDateToShortDateLocalized(value, timeZoneName, languageName) {
|
|
if (!value) {
|
|
return "";
|
|
}
|
|
if (!timeZoneName) {
|
|
timeZoneName = this.getResolvedTimeZoneName();
|
|
}
|
|
if (!languageName) {
|
|
languageName = this.getBrowserLanguages();
|
|
}
|
|
|
|
//parse the date which is identified as utc ("2020-02-06T18:18:49.148011Z")
|
|
let parsedDate = new Date(value);
|
|
|
|
//is it a valid date?
|
|
if (!(parsedDate instanceof Date && !isNaN(parsedDate))) {
|
|
return "not valid";
|
|
}
|
|
|
|
return parsedDate.toLocaleDateString(languageName, {
|
|
timeZone: timeZoneName,
|
|
dateStyle: "short"
|
|
});
|
|
}, ///////////////////////////////////////////
|
|
// Turn a utc date into a displayable
|
|
// short time
|
|
//
|
|
utcDateToShortTimeLocalized(value, timeZoneName, languageName, hour12) {
|
|
if (!value) {
|
|
return "";
|
|
}
|
|
if (!timeZoneName) {
|
|
timeZoneName = this.getResolvedTimeZoneName();
|
|
}
|
|
if (!languageName) {
|
|
languageName = this.getBrowserLanguages();
|
|
}
|
|
|
|
if (!hour12) {
|
|
hour12 = this.getHour12();
|
|
}
|
|
|
|
//parse the date which is identified as utc ("2020-02-06T18:18:49.148011Z")
|
|
let parsedDate = new Date(value);
|
|
|
|
//is it a valid date?
|
|
if (!(parsedDate instanceof Date && !isNaN(parsedDate))) {
|
|
return "not valid";
|
|
}
|
|
|
|
return parsedDate.toLocaleTimeString(languageName, {
|
|
timeZone: timeZoneName,
|
|
timeStyle: "short",
|
|
hour12: hour12
|
|
});
|
|
},
|
|
///////////////////////////////////////////////
|
|
// Convert a utc date to local time zone
|
|
// and return time portion only in iso 8601
|
|
// format (used by time and date picker components)
|
|
//
|
|
utcDateStringToLocal8601TimeOnlyString(value, timeZoneName) {
|
|
if (!value) {
|
|
//if no value, return the current time as expected by the time picker
|
|
} else {
|
|
//ok, the reason for sv-SE is that it's a locale that returns the time already in ISO format and 24hr by default
|
|
//that can change over time so if this breaks that's why
|
|
//also fr-CA does as well as possibly en-CA
|
|
//https://stackoverflow.com/a/58633686/8939
|
|
if (!timeZoneName) {
|
|
timeZoneName = this.getResolvedTimeZoneName();
|
|
}
|
|
|
|
return new Date(value).toLocaleTimeString("sv-SE", {
|
|
timeZone: timeZoneName
|
|
});
|
|
}
|
|
},
|
|
///////////////////////////////////////////////
|
|
// Convert a local time only string with date string
|
|
// to UTC and output as ISO 8601
|
|
// (used by time and date picker components)
|
|
//
|
|
localTimeDateStringToUTC8601String(value, timeZoneName) {
|
|
//https://moment.github.io/luxon/docs/manual/zones.html#creating-datetimes-in-a-zone
|
|
if (!timeZoneName) {
|
|
timeZoneName = this.getResolvedTimeZoneName();
|
|
}
|
|
|
|
//parse in the time in the currently used timezone
|
|
let ret = window.$gz.DateTime.fromISO(value, {
|
|
zone: timeZoneName
|
|
});
|
|
|
|
ret = ret.setZone("utc"); //convert to UTC
|
|
ret = ret.toISO(); //output as ISO 8601
|
|
|
|
return ret;
|
|
},
|
|
///////////////////////////////////////////////
|
|
// UTC Now in api format
|
|
// to UTC and output as ISO 8601
|
|
// (used to set defaults)
|
|
//
|
|
|
|
nowUTC8601String(timeZoneName) {
|
|
if (!timeZoneName) {
|
|
timeZoneName = this.getResolvedTimeZoneName();
|
|
}
|
|
let ret = window.$gz.DateTime.local()
|
|
.setZone(timeZoneName)
|
|
.toUTC()
|
|
.toString();
|
|
return ret;
|
|
},
|
|
///////////////////////////////////////////////
|
|
// Local now timestamp converted to timeZoneName
|
|
// and output as ISO 8601
|
|
// (used to inform server of local client time)
|
|
//
|
|
clientLocalZoneTimeStamp(timeZoneName) {
|
|
if (!timeZoneName) {
|
|
timeZoneName = this.getResolvedTimeZoneName();
|
|
}
|
|
let ret = window.$gz.DateTime.local()
|
|
.setZone(timeZoneName)
|
|
.toString();
|
|
return ret;
|
|
},
|
|
///////////////////////////////////////////////
|
|
// Get default start date time in api format
|
|
// (this is used to centralize and for future)
|
|
defaultStartDateTime(ofType) {
|
|
//ofType in future could be for
|
|
//different areas having different custom start / top times
|
|
//so will set that in all callers for future purposes, but
|
|
//for now, here going to ignore it and just default to now
|
|
//and now plus one hour
|
|
return {
|
|
start: window.$gz.DateTime.local()
|
|
.toUTC()
|
|
.toString(),
|
|
end: window.$gz.DateTime.local()
|
|
.plus({ hours: 1 })
|
|
.toUTC()
|
|
.toString()
|
|
};
|
|
},
|
|
///////////////////////////////////////////////
|
|
// Convert a utc date to local time zone
|
|
// and return date only portion only in iso 8601
|
|
// format (used by time and date picker components)
|
|
//
|
|
utcDateStringToLocal8601DateOnlyString(value, timeZoneName) {
|
|
if (!value) {
|
|
//if no value, return the current time as expected by the time picker
|
|
} else {
|
|
//ok, the reason for sv-SE is that it's a locale that returns the time already in ISO format and 24hr by default
|
|
//that can change over time so if this breaks that's why
|
|
//also fr-CA does as well as possibly en-CA
|
|
//https://stackoverflow.com/a/58633686/8939
|
|
if (!timeZoneName) {
|
|
timeZoneName = this.getResolvedTimeZoneName();
|
|
}
|
|
return new Date(value).toLocaleDateString("sv-SE", {
|
|
timeZone: timeZoneName
|
|
});
|
|
}
|
|
},
|
|
///////////////////////////////////////////////
|
|
// Date/time past or future evaluation
|
|
//
|
|
dateIsPast(value) {
|
|
if (!value) {
|
|
return false;
|
|
}
|
|
|
|
return new Date(value) < new Date();
|
|
},
|
|
///////////////////////////////////////////
|
|
// Turn a decimal number into a local
|
|
// currency display
|
|
//
|
|
currencyLocalized(value, languageName, currencyName) {
|
|
if (value == null) return "";
|
|
if (!languageName) {
|
|
languageName = this.getBrowserLanguages();
|
|
}
|
|
if (!currencyName) {
|
|
currencyName = this.getCurrencyName();
|
|
}
|
|
|
|
return new Intl.NumberFormat(languageName, {
|
|
style: "currency",
|
|
currency: currencyName
|
|
}).format(value);
|
|
},
|
|
///////////////////////////////////////////
|
|
// Turn a decimal number into a local
|
|
// decimal format display
|
|
//
|
|
decimalLocalized(value, languageName) {
|
|
if (value == null) return "";
|
|
if (!languageName) {
|
|
languageName = this.getBrowserLanguages();
|
|
}
|
|
return new Intl.NumberFormat(languageName, {
|
|
minimumFractionDigits: 2
|
|
}).format(value);
|
|
},
|
|
///////////////////////////////////////////
|
|
// Turn a file / memory size number into a local
|
|
// decimal format display and in reasonable human readable range
|
|
//
|
|
humanFileSize(bytes, languageName, si = false, dp = 1) {
|
|
const thresh = si ? 1000 : 1024;
|
|
|
|
if (Math.abs(bytes) < thresh) {
|
|
return bytes + " B";
|
|
}
|
|
|
|
const units = si
|
|
? ["kB", "MB", "GB", "TB", "PB", "EB", "ZB", "YB"]
|
|
: ["KiB", "MiB", "GiB", "TiB", "PiB", "EiB", "ZiB", "YiB"];
|
|
let u = -1;
|
|
const r = 10 ** dp;
|
|
|
|
do {
|
|
bytes /= thresh;
|
|
++u;
|
|
} while (
|
|
Math.round(Math.abs(bytes) * r) / r >= thresh &&
|
|
u < units.length - 1
|
|
);
|
|
|
|
return (
|
|
this.decimalLocalized(bytes.toFixed(dp), languageName) + " " + units[u]
|
|
);
|
|
}
|
|
};
|