Convert JavaScript date to Swift JSON timeIntervalSinceReferenceDate format - javascript

Given a JavaScript date, how can I convert this to the same format as Swift JSON encoding?
e.g. I would like to get a value of 620102769.132999 for the date 2020-08-26 02:46:09

The default Swift JSON encoding outputs a value which is the number of seconds that have passed since ReferenceDate. https://developer.apple.com/documentation/foundation/jsonencoder/2895363-dateencodingstrategy
It seems ReferenceDate is 00:00:00 UTC on 1 January 2001.
https://developer.apple.com/documentation/foundation/nsdate/1409769-init
function dateToSwiftInterval(date: Date): number {
const referenceDate = Date.UTC(2001,0,1);
const timeSpanMs = (date - referenceDate);
return timeSpanMs / 1000;
}
const myDate = new Date(1598366769000);
console.log(dateToSwiftValue(myDate)); // 620102769

As Elwyn says, Swift represents dates as time intervals that are seconds since 1 Jan 2001 UTC. Javascript Dates use milliseconds since 1 Jan 1970 UTC, so all you need to do is adjust by the reference date difference and divide by 1000, e.g.
// Javascript function to convert a Date to a Swift time interval
// date is a Javascript Date, defaults to current date and time
function toSwiftTI(date = new Date()) {
return (date - Date.UTC(2001,0,1)) / 1000;
}
console.log(toSwiftTI());
Since the time difference is a constant, 978307200000, you might just use that instead of calculating it every time, so:
return (date - 978307200000) / 1000;
Going the other way, just multiply by 1,000 and add the constant:
function swiftToDate(ti) {
return new Date(ti * 1000 + 978307200000);
}
console.log(swiftToDate(620102769.132999).toISOString());

Related

How do i get remaining seconds of future date in javascript

So i have an API, which gives me date format like this 11/21/2022 19:00:00 what i need to do is i have to schedule notification for this datetime, but the problem is i am using react-native/expo which accepts the scheduling time in seconds.
How do i convert this datetime to seconds, i mean if today's date is 11/15/2022 12:00:00 and the date on which the notification should be scheduled is 11/16/2022 12:00:00 which means the future date in 1 day ahead of todays date, and 1 day is equal to 86400 seconds, which means i have to trigger notification after 86400 seconds. So how do i get the remaining seconds of the upcoming date?
Use .getTime()
function Date.prototype.getTime() returns number of milliseconds since start of epoch (1/1/1970)
get the number of milliseconds and divide it 1000 to seconds
subtract (round) and you have the difference
according to Date.parse() is only ISO 8601 format of ECMA262 string supported, so use:
new Date("2022-11-16T12:00:00Z")
or new Date(2022,10,16,12)
rather not n̶e̶w̶ ̶D̶a̶t̶e̶(̶"̶1̶1̶/̶2̶1̶/̶2̶0̶2̶2̶ ̶1̶9̶:̶0̶0̶:̶0̶0̶"̶)̶ that can lead to unexpected behaviour
const secondsInTheFuture = new Date("2022-11-16T12:00:00Z").getTime() / 1000;
const secondsNow = new Date().getTime() / 1000;
const difference = Math.round(secondsInTheFuture - secondsNow);
console.log({ secondsInTheFuture, secondsNow, difference });
You can get the epoch time in js with the function + new Date, if you are passing any date value, to new Date(dateValue), please make sure to stringify.
+ new Date
To get the diff b/w these two dates in seconds,
const initialDate = '11/15/2022 12:00:00'
const futureDate = '11/16/2022 12:00:00'
const diffInSeconds = (+ new Date(futureDate) - + new Date(initialDate)) / 1000
ps: epoch time is in milliseconds, hence dividing by 1000.
Solved using dayjs package
const dayjs = require("dayjs")
const d1 = dayjs("2022-11-15 13:00")
const d2 = dayjs("2022-11-16 12:00")
const res = d1.diff(d2) / 1000 // ÷ by 1000 to get output in seconds
console.log(res)

setHours is not a function when converting time from string

I am trying to compare a time in string format to the current time. I've tried setting up two Date objects and calling .Now() on both of them, then on one of them adjusting the time to the time that is in string format by splitting it and parsing both the hours and minutes to integers, but I get the following error:
setHours is not a function
The 'cutoff' value I'm using is '15:00' and when following in the debugger I can see this splits in to split[0] = 15 and split[1] = 00 (this is before they are parsed into integers.
var cutoff = data.CutOff;
var split = cutoff.split(":");
var today = Date.now();
var hours = parseInt(split[0]);
var min = parseInt(split[1]);
today.setHours(hours, min);
if (Date.now() < today) {
// Do Something
}
You want to do new Date() as opposed to Date.now()
new Date creates a Date instance which allows you to access the Date methods.
Date.now() method returns the number of milliseconds elapsed since 1 January 1970 00:00:00 UTC.

Convert excel DATEVALUE to javascript date

I am reading excel data using php and JavaScript. Storing results in variable and showing it on the page.
Simple code example:
var yearend = "< ? php echo ($connection->sheets[0]["cells"][2][5]); ? >";
This works for text and fields with number. But when I format cell as "Date" it returns the values, such as.
Excel field is: 31-Dec-2015 - JavaScript returns value: 40542
I know it is a MS DATEVALUE formatting.
But i need to convert it to date using JavaScript so it shows 31-Dec-2015 or 31 December 2015 only.
So in short:
From Excel 40542 to JavaScript 31 December 2015.
Also, I only need as above, without trailing time and locations, so removing:
00:00:00 00:00 GMT
Also is it possible modify the date to +1 day or -1 day?
//Convert Excel dates into JS date objects
//#param excelDate {Number}
//#return {Date}
function getJsDateFromExcel(excelDate) {
// JavaScript dates can be constructed by passing milliseconds
// since the Unix epoch (January 1, 1970) example: new Date(12312512312);
// 1. Subtract number of days between Jan 1, 1900 and Jan 1, 1970, plus 1 (Google "excel leap year bug")
// 2. Convert to milliseconds.
return new Date((excelDate - (25567 + 1))*86400*1000);
}
try this
toDate(serialDate, time = false) {
let locale = navigator.language;
let offset = new Date(0).getTimezoneOffset();
let date = new Date(0, 0, serialDate, 0, -offset, 0);
if (time) {
return serialDate.toLocaleTimeString(locale)
}
return serialDate.toLocaleDateString(locale)
}
Use the following php function to covert the datevalue into a php timestamp. You could then use standard date functions to format however you wish
function xl2timestamp($xl_date){
return ($xl_date - 25569) * 86400;
}

Javascript: how to add n minutes to unix timestamp

I have a unix timestamp: 1368435600. And a duration in minutes: 75 for example.
Using javascript I need to:
Convert the timestamp to a string format hours:mins (09:00)
Add n minutes to the timestamp: timestamp + 75mins
I tried the moment.js library:
end_time = moment(start_time).add('m', booking_service_duration);
booking_service_duration was 75 but it added an hour. I'd also rather not have to use another js library
To add 75 minutes, just multiply by 60 to get the number of seconds, and add that to the timestamp:
timestamp += 75 * 60
To convert to hours:mins you will have to do a bit more math:
var hours = Math.floor(timestamp/60/60),
mins = Math.floor((timestamp - hours * 60 * 60) / 60),
output = hours%24+":"+mins;
Unix time is the number of seconds that have elapsed since 1 January 1970 UTC.
To move that time forward you simply add the number of seconds.
So once you have the minutes, the new timestamp is oldTime + 60*minutes
For the conversion look up parsing libraries, there is code out there for this, do some research.
So you want to convert a timestamp you have, timestamp, to locale time string after adding some time interval, specifically minutes, to it.
Whether you have a kind of date-time string or a kind of epoch mili/seconds, just create a Date object:
const date = new Date(timestamp);
Keep in mind since what you need to do require to add/substract some numbers (your case: minutes) to another number, not some date object or some date-time string, and that number is the epoch mili/secods of your date. So, always you will need the number representation of your date in mili/seconds. JavaScript Date.prototype.getTime() does return epoch miliseconds of your date. Use it:
const miliseconds = date.getTime();
Add as many as miliseconds to it:
const newMiliseconds = miliseconds + (75 * 60 * 1000);
After that, as you said you need a date-time string, well a portion of it; locale time string, you will need to go all the way back; from numbers to date object and to a date-time string:
const newDate = new Date(newMiliseconds);
const newTimestamp = newDate.toString();
Or instead of getting the whole string of it, use the following specialized method to get the format/portion of the string representation of the date object that you like directly:
const newTimestamp = newDate.toLocaleTimeString(); // "12:41:43"
Finally, all you have to do is to just strip the last semicolon and seconds to get hours:minutes format:
const newHoursMins = newTimestamp.slice(0, -3);
Better make a function of it:
function timestampPlus(timestamp, milisecondsDifference, toStringFunc = Date.prototype.toString) {
const date = new Date(timestamp);
const miliseconds = date.getTime();
const newMiliseconds = miliseconds + milisecondsDifference;
const newDate = new Date(newMiliseconds);
const newTimestamp = toStringFunc.call(newDate); // a bit advanced stuff here to let you define once and use whatever kind to string method you want to use, defaults to toString()
return newTimestamp;
}
I left the final formatting out here. You can use this for substraction as well by pasing a negative second argument. Note the seconds argument is in miliseconds and unix timestamp varies and might given to you as seconds instead, in which case you will need to convert it to miliseconds or change the above funciton definition.
function timestampPlus(timestamp, milisecondsDifference, toStringFunc = Date.prototype.toString) {
const date = new Date(timestamp);
const miliseconds = date.getTime();
const newMiliseconds = miliseconds + milisecondsDifference;
const newDate = new Date(newMiliseconds);
const newTimestamp = toStringFunc.call(newDate); // a bit advanced stuff here to let you define once and use whatever kind to string method you want to use, defaults to toString()
return newTimestamp;
}
console.log("new Date(1368435600*1000).toLocaleTimeString(): ", new Date(1368435600*1000).toLocaleTimeString())
console.log("timestampPlus(1368435600*1000, 75*60*1000, Date.prototype.toLocaleString): ", timestampPlus(1368435600*1000, 75*60*1000, Date.prototype.toLocaleTimeString))
Apart from what you need, for last parameter, toStringFunc, your options vary and encompasses all related Date methods, the are on Date.prototype:
toString
toDateString
toTimeString
toLocaleString
toLocaleDateString
toLocaleTimeString
toIsoString
toUTCString
toGMTString
toJSON

How to the get the beginning of day of a date in javascript -- factoring in timezone

I am struggling to find out the beginning of day factoring in timezones in javascript. Consider the following:
var raw_time = new Date(this.created_at);
var offset_time = new Date(raw_hour.getTime() + time_zone_offset_in_ms);
// This resets timezone to server timezone
var offset_day = new Date(offset_time.setHours(0,0,0,0))
// always returns 2011-12-08 05:00:00 UTC, no matter what the offset was!
// This has the same issue:
var another_approach_offset_day = new Date(offset_time.getFullYear(),offset_time.getMonth(),offset_time.getHours())
I expect when i pass a Pacific Timezone offset, to get: 2011-12-08 08:00:00 UTC and so on.
What is the correct way to achieve this?
I think that part of the issue is that setHours method sets the hour (from 0 to 23), according to local time.
Also note that I am using javascript embedded in mongo, so I am unable to use any additional libraries.
Thanks!
Jeez, so this was really hard for me, but here is the final solution that I came up with the following solution. The trick was I need to use setHours or SetUTCHours to get the beginning of a day -- the only choices I have are system time and UTC. So I get the beginning of a UTC day, then add back the offset!
// Goal is given a time and a timezone, find the beginning of day
function(timestamp,selected_timezone_offset) {
var raw_time = new Date(timestamp)
var offset_time = new Date(raw_time.getTime() + selected_timezone_offset);
offset_time.setUTCHours(0,0,0,0);
var beginning_of_day = new Date(offset_time.getTime() - selected_timezone_offset);
return beginning_of_day;
}
In JavaScript all dates are stored as UTC. That is, the serial number returned by date.valueOf() is the number of milliseconds since 1970-01-01 00:00:00 UTC. But, when you examine a date via .toString() or .getHours(), etc., you get the value in local time. That is, the local time of the system running the script. You can get the value in UTC with methods like .toUTCString() or .getUTCHours(), etc.
So, you can't get a date in an arbitrary timezone, it's all UTC (or local). But, of course, you can get a string representation of a date in whatever timezone you like if you know the UTC offset. The easiest way would be to subtract the UTC offset from the date and call .getUTCHours() or .toUTCString() or whatever you need:
var d = new Date();
d.setMinutes(d.getMinutes() - 480); // get pacific standard time
d.toUTCString(); // returns "Fri, 9 Dec 2011 12:56:53 UTC"
Of course, you'll need to ignore that "UTC" at the end if you use .toUTCString(). You could just go:
d.toUTCString().replace(/UTC$/, "PST");
Edit: Don't worry about when timezones overlap date boundaries. If you pass setHours() a negative number, it will subtract those hours from midnight yesterday. Eg:
var d = new Date(2011, 11, 10, 15); // d represents Dec 10, 2011 at 3pm local time
d.setHours(-1); // d represents Dec 9, 2011 at 11pm local time
d.setHours(-24); // d represents Dec 8, 2011 at 12am local time
d.setHours(52); // d represents Dec 10, 2011 at 4am local time
Where does the time_zone_offset_in_ms variable you use come from? Perhaps it is unreliable, and you should be using Date's getTimezoneOffset() method. There is an example at the following URL:
http://www.w3schools.com/jsref/jsref_getTimezoneOffset.asp
If you know the date from a different date string you can do the following:
var currentDate = new Date(this.$picker.data('date'));
var today = new Date();
today.setHours(0, -currentDate.getTimezoneOffset(), 0, 0);
(based on the codebase for a project I did)
var aDate = new Date();
var startOfTheDay = new Date(aDate.getTime() - aDate.getTime() % 86400000)
Will create the beginning of the day, of the day in question
You can make use of Intl.DateTimeFormat. This is also how luxon handles timezones.
The code below can convert any date with any timezone to its beginging/end of the time.
const beginingOfDay = (options = {}) => {
const { date = new Date(), timeZone } = options;
const parts = Intl.DateTimeFormat("en-US", {
timeZone,
hourCycle: "h23",
hour: "numeric",
minute: "numeric",
second: "numeric",
}).formatToParts(date);
const hour = parseInt(parts.find((i) => i.type === "hour").value);
const minute = parseInt(parts.find((i) => i.type === "minute").value);
const second = parseInt(parts.find((i) => i.type === "second").value);
return new Date(
1000 *
Math.floor(
(date - hour * 3600000 - minute * 60000 - second * 1000) / 1000
)
);
};
const endOfDay = (...args) =>
new Date(beginingOfDay(...args).getTime() + 86399999);
const beginingOfYear = () => {};
console.log(beginingOfDay({ timeZone: "GMT" }));
console.log(endOfDay({ timeZone: "GMT" }));
console.log(beginingOfDay({ timeZone: "Asia/Tokyo" }));
console.log(endOfDay({ timeZone: "Asia/Tokyo" }));

Categories