I have a form that sends the value of year and months from an input and then while sending the value to the server I am converting that values to ISO string like that:
const toIsoString = (year, month, day) => moment(new Date(year, month - 1, day)).toISOString(true).split('.')[0];
And then in the values I am using it like this.
StartDate: toIsoString(data.StartYear, parseInt(data.StartMonth, 10), 1),
In that case It is sending the value like this:
startDate: "2021-01-01T00:00:00"
Does anybody know why the Time period is being ignored and how can I also send the time period with the year, month and date values.Any helps would be highly appreciated.Thanks...
Does anybody know why the Time period is being ignored and how can I also send the time period with the year, month and date values.Any helps would be highly appreciated.
The time isn't ignored. In the function:
const toIsoString = (year, month, day) =>
moment(new Date(year, month - 1, day)).toISOString(true).split('.')[0];
the values for hour, minute, second and millisecond are omitted so they default to 0. What time are you expecting?
If you want the current local time added to the date, then create a date and set the year, month and day to the required values without modifying the time (though I don't know why you'd want to do that).
Rather than creating a string that you then need to further process, tell moment.js the format you want:
function toIsoString (year, month, day) {
return moment(new Date().setFullYear(year, month-1, day)).format('YYYY-MM-DD HH:mm:ss');
}
console.log(toIsoString('2021','1','1'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.26.0/moment.min.js"></script>
You can also do that without a library, see How to format a JavaScript date, e.g.:
function formatDate(year, month, date) {
let z = n => (n<10?'0':'') + Number(n);
return `${year}-${z(month)}-${z(date)} ${
new Date().toLocaleString('en',{
hour12:false,
hour:'2-digit',
minute:'2-digit',
second:'2-digit'})
}`;
}
console.log(formatDate('2021','1','01'))
Its because you are only setting year, month and date while creating moment object. You are not setting time
You should do something like
const toIsoString = (year, month, day) => {
const currDate = moment(new Date());
currDate.year(year);
currDate.month(month - 1);
currDate.date(day);
return currDate.toISOString(true).split('.')[0];
}
Or simply use set function
const toIsoString = (year, month, day) => {
const currDate = moment(new Date());
currDate.set({
'year': year,
'month': (month - 1),
'date': day
});
return currDate.toISOString(true).split('.')[0];
}
Related
I have a date from a vuetify date picker. I take that date and I am trying to format it to MM/DD/YYYY however I need to first add a year to it then subtract one day. So January 1 2022 will become December 31 2022. My code is as follows:
formatDateNextYear(date) {
if (!date) return null
let a = new Date(date);
a.setDate(a.getDate() - 1)
a.setFullYear(a.getFullYear+1)
const [year, month, day] = a.split('-')
return `${month}/${day}/${year}`
}
My issue is this does not seem to add the year and is not formatted correctly.
You forgot to call getFullYear, and instead of trying to format it yourself, you can use toLocaleDateString and pass in the locale you want the format to be in:
function formatDateNextYear(date) {
if (!date) return null;
let a = new Date(date);
a.setDate(a.getDate() - 1);
a.setFullYear(a.getFullYear() + 1);
return a.toLocaleDateString("en-US");
}
console.log(formatDateNextYear(new Date("01/01/2022")));
I'm trying to calculate the datetime in UTC, i have the bellow code and using Luxon
weeklyDish.orderBeforeTime = timeZoneToUTC(
"Europe/Amsterdam",
year,
month,
day,
hours
);
function timeZoneToUTC(timezone, year, month, day, hours) {
const dateObj = `${year}-${month}-${day} ${hours}:00`;
const datetime = DateTime.fromFormat(dateObj, "yyyy-M-d H:mm", {
zone: timezone,
});
return datetime.toUTC().toString();
}
The code above always return the wrong hour.
How can I get the year, month, hour and return a UTC string to save in the DB?
I'm going to be migrating data that has date as string (example: "2020-12-13"), how can I convert it to UTC date and subtract days correctly?
You need to show an example to demonstrate your issue. The following shows use of Luxon's UTC and setZone methods that both seem to correctly convert a date set for "Europe/Amsterdam".
Note that the string passed to DateTime.fromISO must form a valid ISO 8601 timestamp like YYYY-MM-DDTHH.
let DateTime = luxon.DateTime;
let [tz, y, m, d, h] = ["Europe/Amsterdam", '2020', '11', '30', '12'];
let date = DateTime.fromISO(`${y}-${m}-${d}T${h}`, { zone: "Europe/Amsterdam" });
console.log(tz + '\n' + date.toString());
let dateUTC = date.setZone('UTC');
console.log('setZone to UTC\n' + dateUTC.toString());
let dateUTC2 = date.toUTC();
console.log('toUTC method\n' + dateUTC2.toString());
<script src="https://cdn.jsdelivr.net/npm/luxon#1.25.0/build/global/luxon.min.js"></script>
PS Amsterdam standard time is +1, daylight saving time is +2.
If the date is already parsed, you can use the date constructor directly. However, the constructor depends on the local timezone, luckily you can use Date.UTC instead.
The tricky part is about the timezone, which is not supported in the constructor, but it's a simple addition anyway.
So I'd wager something like so should work:
function timeZoneToUTC(timezone, year, month, day, hours) {
return new Date(Date.UTC(year, month - 1, day, hours + timezone));
}
Note: the month parameter is an index (0-based), so if you have 1=January, you need to decrease your month by one (as in my example).
Edit: uh, apparently, Date.UTC returns a timestamp, so you need to use the constructor anyway.
I am passing in time values departureTime such as '12:00' here. Then I try to convert it into a date and perform a subtraction. However, the result of timeOfDeparture and then time till departure is invalid. How can I fix this and make everything in a uniform type?
const timeNow = new Date();
console.log('TIME NOW', timeNow)
const timeOfDeparture = new Date(departureTime);
console.log('TIME of Departure', timeOfDeparture)
const timeTillDeparture = Math.floor((timeOfDeparture.valueOf() - timeNow.valueOf()) / 60000);
console.log('TIME TILL DEP', timeOfDeparture)
Example console logs:
TIME NOW Tue Oct 06 2020 15:47:35 GMT+0200 (Central European Summer Time)
TIME of Departure Invalid Date
TripTimes.tsx:17 TIME TILL DEP NaN
The date object doesn't take hours as an argument. you can read more about it here
There are four ways of instantiating a date:
var d = new Date();
var d = new Date(milliseconds);
var d = new Date(dateString);
var d = new Date(year, month, day, hours, minutes, seconds, milliseconds);
If your app relies on date manipulation, or if you want to manipulate dates more easily, consider using helper libraries like momentJs.
For example, if your departure time is on the same date but just on a different hour, your departure time using momentJs will be
moment().hour(departureHour).minute(departureMinute);
When you are creating a Javascript Date object you cannot pass only hours and minutes. You can use the empty constructor or data constructor
new Date(year, month, date, hours, minutes, seconds, ms)
but the first two arguments (year and month) are obligatory at least. You could get data from timeNow and add the time values from departureTime. Example:
const timeNow = new Date();
console.log('TIME NOW', timeNow)
let departureTimeArray = departureTime.split(":");
console.log('Hour of Departure', departureTimeArray[0]);
console.log('Minutes of Departure', departureTimeArray[1]);
const timeOfDeparture = new Date(timeNow.getFullYear(), timeNow.getMonth(), timeNow.getDate(), departureTimeArray[0], departureTimeArray[1]);
console.log('TIME of Departure', timeOfDeparture);
const timeTillDeparture = Math.floor((timeOfDeparture.valueOf() - timeNow.valueOf()) / 60000);
console.log('TIME TILL DEP', timeOfDeparture)
I hope this solution helps you.
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" }));
How can I create a date object which is less than n number of months from another date object? I am looking for something like DateAdd().
Example:
var objCurrentDate = new Date();
Now using objCurrentDate, how can I create a Date object having a date which is six months older than today's date / objCurrentDate?
You can implement very easily an "addMonths" function:
function addMonths(date, months) {
date.setMonth(date.getMonth() + months);
return date;
}
addMonths(new Date(), -6); // six months before now
// Thu Apr 30 2009 01:22:46 GMT-0600
addMonths(new Date(), -12); // a year before now
// Thu Oct 30 2008 01:20:22 GMT-0600
EDIT: As reported by #Brien, there were several problems with the above approach. It wasn't handling correctly the dates where, for example, the original day in the input date is higher than the number of days in the target month.
Another thing I disliked is that the function was mutating the input Date object.
Here's a better implementation handling the edge cases of the end of months and this one doesn't cause any side-effects in the input date supplied:
const getDaysInMonth = (year, month) => new Date(year, month, 0).getDate()
const addMonths = (input, months) => {
const date = new Date(input)
date.setDate(1)
date.setMonth(date.getMonth() + months)
date.setDate(Math.min(input.getDate(), getDaysInMonth(date.getFullYear(), date.getMonth()+1)))
return date
}
console.log(addMonths(new Date('2020-01-31T00:00:00'), -6))
// "2019-07-31T06:00:00.000Z"
console.log(addMonths(new Date('2020-01-31T00:00:00'), 1))
// "2020-02-29T06:00:00.000Z"
console.log(addMonths(new Date('2020-05-31T00:00:00'), -6))
// "2019-11-30T06:00:00.000Z"
console.log(addMonths(new Date('2020-02-29T00:00:00'), -12))
// "2019-02-28T06:00:00.000Z"
Create date object and pass the value of n, where n is number(add/sub) of month.
var dateObj = new Date();
var requiredDate= dateObj.setMonth(dateObj.getMonth() - n);
var oldDate:Date = new Date();
/*
Check and adjust the date -
At the least, make sure that the getDate() returns a
valid date for the calculated month and year.
If it's not valid, change the date as per your needs.
You might want to reset it to 1st day of the month/last day of the month
or change the month and set it to 1st day of next month or whatever.
*/
if(oldDate.getMonth() < n)
oldDate.setFullYear(oldDate.getFullYear() - 1);
oldDate.setMonth((oldDate.getMonth() + n) % 12);
You have to be careful because dates have a lot of edge cases. For example, merely changing the month back by 6 doesn't account for the differing number of days in each month. For example, if you run a function like:
function addMonths(date, months) {
date.setMonth((date.getMonth() + months) % 12);
return date;
}
addMonths(new Date(2020, 7, 31), -6); //months are 0 based so 7 = August
The resulting date to return would be February 31st, 2020. You need to account for differences in the number of days in a month. Other answers have suggested this in various ways, by moving it to the first of the month, or the last of the month, or the first of the next month, etc. Another way to handle it is to keep the date if it is valid, or to move it to the end of the month if it overflows the month's regular dates. You could write this like:
function addMonths(date, months) {
var month = (date.getMonth() + months) % 12;
//create a new Date object that gets the last day of the desired month
var last = new Date(date.getFullYear(), month + 1, 0);
//compare dates and set appropriately
if (date.getDate() <= last.getDate()) {
date.setMonth(month);
}
else {
date.setMonth(month, last.getDate());
}
return date;
}
This at least ensures that the selected day won't "overflow" the month that it is being moved to. Finding the last day of the month with the datePart = 0 method is documented here.
This function still leaves a lot to be desired, as it doesn't add years and you can't subtract more than a year (or you will run into a new issue with negatives being involved). However, fixing those and the other issues you may run into (namely timezones) will be left as an exercise for the reader.