MomentJS is sometimes adding the wrong amount of hours - javascript

So what i'm simply trying to achieve a feature where i add X.X amount of hours to a 24h time. The issue is for the time 00:00, an incorrect amount of hours is added
The code i wrote works for the most part. It works for every possible time except 0:00.
If i have 01:30 and i add 1h it gives me 02:30. If I have 02:30 and i add 1.5h it gives me 04:00.
So heres this issue. When i have 00:00 and i add 1h i get 01:06...seems to make no sense and i was hoping someone with more momentJS experience might have some thoughts or ideas on the matter. Heres the code
If i have 00:00 and have 3.5 i get 03:06. This all only seems to happen when i start with 00:00. Kind of driving me crazy
console.log(timesheetRows[i][p]); //prints 0:00
console.log(Number(hours)); // prints 1
timesheetRows[i][p] = moment.utc(timesheetRows[i][p], 'hh:mm').add(Number(hours), 'hours').format('HH:MM');

You're using the wrong formats, hh stands for 12 hours and MM stands for two digits month number.
Use something like this:
moment.utc(timesheetRows[i][p], 'HH:mm').add(Number(hours), 'hours').format('HH:mm');

Related

How to work with Moment.js to return time in a 24-hours format when adding to it?

I get hours as strings in my app, e.g. "2230". I would like to be able to add minutes to it, so as to simulate the time that it will be after those minutes have been added to it, e.g.
//"2230" + "60"mins = "23:30"
//"2230" + "180"mins = "02:30"
I read that Moment.js could be a solution to this, but I couldn't figure out:
what the right way to format the hours initially is with moment("2230").format()
how to add minutes to it
how to make it behave like a 24-hour clock when adding to it
Moment is a great tool for doing this. It takes some syntax tricks to get it right, but I think this is what you're looking for:
moment("2230", "HH:mm")
.add(60, "minutes")
.format("HH:mm")
Feel free to play around with it here:
https://codesandbox.io/s/proud-pine-lz0fs?file=/src/index.js
As you can see, as long as your time string is always 4 characters long, moment can extract the HH:mm format, then you can add minutes, and then format the final output to HH:mm again.
Here are 2 great resources:
https://techstream.org/Bits/Javascript/Javascript-Parse-time
https://flaviocopes.com/momentjs/
Hope that helps!
First you have to split this string to get the hours and minutes from it.
const s= "2230"
const hour = s.substring(0,2);
const min = s.substring(2,4);
After that you can easily pass this hours and min to a moment.
const time = moment()
.set({"hour": hour, "minute": min})
.add(60, 'minutes')
.format("HH:mm");
the .set is to set the time (hours minutes)
the .add is to add the minutes you wanted to add
the .format is to format the output as you pleased,
NOTE the capital "HH" means 24/h clock while "hh" means 12/h clock

Moment display seconds as 'm:ss'

I am trying to use moment to display 2 seconds like this 0:02.
I expected the following code to work but unfortunately it just displays as0:00. This is based on this section of the docs.
moment(2).format('m:ss');
Can anyone advise where I am going wrong? I have read through the docs and tried numerous approaches with no luck.
You do it as
moment().minutes(0).second(2).format('m:ss')
https://jsfiddle.net/4eqL594p/
But this also sets minutes as 0.
EDIT: As another answerer had pointed out, you could also do
moment({seconds: 2}).format('m:ss')
Try Unix method, it accept an integer value representing the number of seconds since the Unix Epoch (Jan 1 1970 12AM UTC)
Example:
moment.unix(2).format('m:ss');
Demo:
console.log(moment.unix(2).format('m:ss'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.2.1/moment.min.js"></script>

Correctly treating DST shift with momentJS

I've came across something that I thought it was right, but now taking a closer look something is clearly wrong.
I'm on a project of a pill reminder app where someone can set notifications to remind him/her of taking pills in the correct time. There're medicines which a person can take for the rest of his life. And in that case I don't set alerts for years, I set for 3 months max and, when he takes one and mark it as done, I set another alert for 3 months later starting on that date/time.
This app will be released only in Brazil and we have Daylight Saving Time here. When it shifts to DST time the clocks must be adjusted to -1 hour after midnight, when going off DST it gains 1 hour.
For this project I'm using Firebase, Ionic 2, the LocalNotification Plugin and Moment JS.
I have to make a story of the user because other user can see if he's taking it correctly, so I use Moment JS to manipulate the datetime and save the notification and create a node for that user in firebase with UNIX time.
LET'S FINALLY GO TO THE PROBLEM.
When saving a date I check if this date is DST, if it is I add +3 hours to it, if it's not I add +2. I need to add this because when I wrap the isoString in the Moment() function it gives me -3 hours or -2 hours (Haven't searched for this, but I think Moment uses USA time).
This works fine if I'm saving dates inside DST times if I'm in DST time, if in some case I'm not on DST and save a notification for a DST time day it saves with +2 hours.
AN EXAMPLE
The DST time will shift to in DST on October 15. If I need to save 30 notifications, one per day everyday as 12AM, starting at October 1 up to October 30. From day 1 to day 15 the dates will be right, from day 16 to 30 they'll be with +2 hours.
Here's the basic code I use:
// THIS'LL SET MY DATEPICKER TO THE DATE/HOUR I'M IN.
minDate: any = Moment().isDST ? Moment().subtract(3, 'h').toDate().toISOString() : Moment().subtract(2, 'h').toDate().toISOString();
// THIS'LL CONVERT THE SELECTED DATE TO A UNIX TIME IN WICH I'LL USE TO SAVE THE NOTIFICATION AND THE MEDICATION DATA ON FIREBASE
unixConverted = Moment(this.minDate).isDST ? Moment(this.minDate).add(3, 'h').unix() : Moment(this.minDate).add(2, 'h').unix();
What is strange is that using Moment().unix() alone it give me the right time I'm in, if I use Moment(this.minDate).unix() it gives me -2 or -3 hours of the hour I selected.
So if it's in DST (in which I've set my clock to -1 hour) I add 3, if not I add 2.
So how is the proper way to manipulate this DST shift?
Is there a better way to do this than using DST?
Am I right using this logic or is this much more complex than what I think?
Ok so i've found a better way without using .isDST() method.
Simple use Moment().add(Moment().utcOffset(), 'm'), this'll get the current moment time and add the offset in minutes.
The .add() and .subract() methods makes Moment return the UTC time.
The utcOffset() returns a positive or negative number of minutes (representing hours) from UTC, like -60 or 180. So i'll get the correct respecting the time shift.
Worked like a charm for me.

Number of hours to HH:MM with Moment.js (or without)

I have very simple problem, but couldn't find good simple DRY solution. I want to convert number of hours to HH:MM format. My try with Moment.js is:
var hours = 10.5
var hour_string = moment(hours*3600*1000).format('HH:MM')
But unfortunately I get:
"11:01"
and have no idea why. Of course my wanted result is "10:30".
I'd like just do it in the easiest way, similar as I can do in Rails:
Time.at(hours*3600).utc.strftime("%H:%M")
Any ideas?
Okay, I found the reason. "MM" means months, not minutes, which are "mm". And the hour shift was caused by timezones, which we can omit using the utc function. The final solution is:
moment.utc(hours*3600*1000).format('HH:mm')

How to do total 24 hrs validation maintaning 12 hrs format using javascript?

In my web app Form i ve two fields called startTime,closeTime which are repeated in every row of the table.now i ve to validate for 24hrs(1440 mins) from startTime of the first row to closeTime of the last row.but user enters time in 12 hr format means if startTime of the first row is 08:00 am then i ve to check upto 08:00 am of next day(every thing i am converting into minutes).i tried in several ways but unable to caliculations missing in am to pm/pm to am please help me.following is my code (onclick of first column of every row it ll be called)
var timeArray=[""],timeArray1=[""],timeNoon,closeNoon,temp=0,sumTime=0;
function checkTime(){
var startTime,closeTime;
if(rowIndex!=0){//rowIndex is current row index
startTime=document.getElementById("logSheetDataTable").rows[rowIndex-1].cells[j].childNodes[0].tBodies[0].rows[0].cells[1].childNodes[0].value;
closeTime = document.getElementById("logSheetDataTable").rows[rowIndex-1].cells[j].childNodes[0].tBodies[0].rows[1].cells[1].childNodes[0].value;
timeNoon=startTime.substring(6);//to get am or pm
startTime = startTime.substring(0,5);//to get tome 08:00
timeArray = startTime.split(":");
closeNoon=closeTime.substring(6);//to get am or pm
closeTime1=closeTime.substring(0,5);
timeArray1=closeTime1.split(":");
if(timeNoon.toLowerCase()=="pm"){
startMin=parseInt((timeArray[0]*60))+parseInt(timeArray[1])+720;
}else if(timeNoon.toLowerCase()=="am"){
startMin=parseInt((timeArray[0]*60))+parseInt(timeArray[1]);
}
if(closeNoon.toLowerCase()=="pm"){
endMin=parseInt((timeArray1[0]*60))+parseInt(timeArray1[1]+720);
}else if(closeNoon.toLowerCase()=="am"){
endMin=parseInt((timeArray1[0]*60))+parseInt(timeArray1[1]);
}
if(startMin<endMin){
temp=endMin-startMin;
}else if(startMin>endMin){
temp=(1440-startMin)+endMin;
}
sumTime=sumTime+temp;
alert("sum: "+sumTime);
}
for sumTime i ve to check for 1440 mins.
It sounds like you've got a table that looks something like this:
START END
08:00 am 10:00 am
10:00 am 03:00 pm
03:00 pm 08:00 am
And you're saying that you want to validate that 24 hours has passed from the START in the first row and the END in the last row. If that's all you want to do what's all the rest of your code for?
The calculation you've got in your code looks like you're adding up the time between each START and END on the row, then summing these, presumably to check if you've got to 24 hours. You're not checking the first START + last END, so is this valid (three lots of 8 hours==24)?
START END
01:00 am 09:00 am
01:00 am 09:00 am
01:00 am 09:00 am
When you're splitting out the string, you're always taking the first 5 characters and assuming that they are of the form HH:MM. Is this always correct (you're never going to encounter a time where for example the 0 prefix is missing, so you have 8:00am? Are you sure that there will always be exactly 1 space after the time, before the am/pm? Are you sure there is nothing after the am/pm? All of these will effect whether or not your string parsing works correctly...
Some of the ways that you're extracting numbers look a bit dodgy to me. For example:
startMin=parseInt((timeArray[0]*60))+parseInt(timeArray[1])+720;
Look carefully at the brackets. You calling parseInt on the result of (timeArray[0]*60). Presumably this should be calling it, before you try to do mathematical operations:
startMin=(parseInt(timeArray[0])*60)+parseInt(timeArray[1])+720;
This is a common problem with a lot of your calls to parseInt which may be causing some unexpected issues...
Now, looking at the calculation for the time difference between each start and end on a single row...
If the time is pm, add twelve hours (720 minutes) to convert it to 24 hours clock. You seem to be trying to do this, you're also converting it into minutes at the same time.
Now, you have three scenarios.
START == END - This will either be 0 or 24 hours, currently you don't seem to cater for this.
START > END - The day has rolled over between the START time and END time. So, you need to calculate the (time to the end of the day) + END time. So in minutes, you'd have 1440 - startMin + endMin. You seem to be doing this correctly...
END > START - End is later than start, so you just need the difference: endMin - startMin, again you seem to be doing this correctly.
So, there must be something wrong with your code. I've had a bit of a fiddle and it turns our your problem is basically your bracketing. Because you've got them in the wrong place, your numbers are being used as strings sometimes + numbers others, so sometimes instead of addition, you get concatenation of the values which throws you way off...
The relevant fixes are:
if(timeNoon.toLowerCase()=="pm"){
startMin=(parseInt(timeArray[0])*60)+parseInt(timeArray[1])+720;
}else if(timeNoon.toLowerCase()=="am"){
startMin=(parseInt(timeArray[0])*60)+parseInt(timeArray[1]);
}
if(closeNoon.toLowerCase()=="pm"){
endMin=(parseInt(timeArray1[0])*60)+parseInt(timeArray1[1])+720;
}else if(closeNoon.toLowerCase()=="am"){
endMin=(parseInt(timeArray1[0])*60)+parseInt(timeArray1[1]);
}

Categories

Resources