Moment js - displaying days and hours away from a date - javascript

I am working on a project that requires this kind of text response on a date object.
"1 day 7 hours away"
--- it needs to be this way - not "31 hours away" or "1 day away"
-- also I am using moment js - as I am doing language switching between English and German - so I've tapped into the moment.js language locale
moment.locale('de')
I am using moment js - currently I've created a fake date object
var futureDate = new Date()
futureDate.setDate(futureDate.getDate() + 1)// add a day
futureDate.setHours(7)// add 7 hours
when I try and render the moment js
moment(futureDate).endOf('day').fromNow()
it just says "in a day"
How do I modify the moment function to handle 1 day 7 hours -- and maybe re-jig the sentence?
--- code snippet attempt
moment.locale('de') // switch between en and de -- english and german
var futureDate = new Date()
futureDate.setDate(futureDate.getDate() + 1)// add a day
futureDate.setHours(7)// add 4 hours
// Results in hours
console.log(moment(futureDate).endOf('day').fromNow());
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.min.js"></script>
code test 2 using difference
moment.locale('de') // switch between en and de -- english and german
var a = moment();
var b = moment(a).add(31, 'hours');
// Results in days
console.log(b.diff(a, 'days'));
console.log(b.diff(a, 'days', true));
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.17.1/moment.min.js"></script>

You can use relativeTimeThreshold and relativeTime (key of moment.updateLocale) to customize how moment shows relative time (e.g. the fromNow() output).
In your case, you can:
Adjust threshold to get difference in seconds (see: How to make moment.js show relative time in seconds?).
Create a duration object using moment.duration(Number, String).
Use moment-duration-format plug-in to show duration value in the format you prefer.
Here a live sample:
var momEn = moment().add({d:1, h:7});
var momDe = moment().locale('de').add({d:1, h:7});
console.log(momEn.fromNow()); // in a day
console.log(momDe.fromNow()); // in einem Tag
// Change relativeTimeThreshold
moment.relativeTimeThreshold('s', 60*60*24*30*12);
// Update relative time
moment.updateLocale('en', {
relativeTime : {
s: function (number, withoutSuffix, key, isFuture){
return moment.duration(number, 's').format('d [day] h [hour]');
},
}
});
moment.updateLocale('de', {
relativeTime : {
s: function (number, withoutSuffix, key, isFuture){
return moment.duration(number, 's').format('d [Tag] h [Uhr]');
},
}
});
console.log(momEn.fromNow()); // in 1 day 7 hour
console.log(momDe.fromNow()); // in 1 Tag 7 Uhr
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment-with-locales.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-duration-format/1.3.0/moment-duration-format.min.js"></script>
Unfortunately you have to manually update each locale you need to support.

You can do it with moment-duration-format or with moment.diff like so:
let futureDate = new Date ()
futureDate.setDate (futureDate.getDate () + 1)// add a day
futureDate.setHours (7)
let start = moment ()
let end = moment (futureDate)
// 1st solution: with moment-duration-format
console.log (moment.duration (end.diff (start)).format ('d [days] hh [hours]', { trim: false }))
// 2nd solution: diff without moment-duration-format
let hoursDuration = end.diff (start, 'hours')
console.log (Math.floor (hoursDuration / 24) + ' days ' + (hoursDuration % 24) + ' hours')
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment-duration-format/1.3.0/moment-duration-format.min.js"></script>
The first solution requires the additional moment-duration-format module, whereas the second does everything using moment.js only. Also, don't forget to npm install moment-duration-format before requiring it.

Edit: Since you mentioned you'd like to stick with Moment.js, they have moment#diff available:
var a = moment([2007, 0, 29]);
var b = moment([2007, 0, 28]);
a.diff(b, 'days') // 1
Found from: https://stackoverflow.com/a/42187373/2803743
I'd use countdown.js for this.
var futureDate = new Date()
futureDate.setDate(futureDate.getDate() + 1)// add a day
futureDate.setHours(7)// add 7 hours
var timePassed = countdown(Date.now().toString(), futureDate, countdown.DAYS|countdown.HOURS);
console.log(timePassed);
timePassed is a lovely object; in this example:
days: 0
end: Tue Jul 04 2017 07:17:41 GMT+0300 (EEST)
hours: 12
start: Mon Jul 03 2017 19:17:41 GMT+0300 (EEST)
units: 18
value: 43200000
Which you can then concat to your desired string.
It's not really documented well, but the lib also has a CDN
https://cdnjs.com/libraries/countdown

Related

Why i get added 5 hours instead 4 on daylight saving time when i use the add method and how can i resolve it?

I need to add 4 hours to my moment js date. So for that i am using
/* this timestamp is this date 27-03-2045 00:00 */
const someday = moment(2374178400000);
const addedFourHours = someday.add(4, 'hours');
on 27 March the DST is already passed and i get exactly 4 hours added and the end date in addedFoursHours is Mon Mar 27 2045 04:00:00 GMT+0200.
But when i try date when DST is happening for example 26 March on midnight
/* this timestamp is this date 26-03-2045 00:00 */
const someday = moment(2374095600000);
const addedFourHours = someday.add(4, 'hours');
then i get Sun Mar 26 2045 05:00:00 GMT+0200. In previous case i got 04:00 time when i added 4 hours after midnight. Why in DST time i get 05:00 time ?
How can i solve this ?
You want to add 3, 4 or 5 hours depending on the date, but you want to set specific values for the hours. Read the hour value, add 4 and set the value:
const today = moment(2374178400000);
const four = moment(today).hours(today.hour() + 4);
const eight = moment(four).hours(four.hour() + 4);
const twelve = moment(eight).hours(eight.hour() + 4);
const sixteen = moment(twelve).hours(twelve.hour() + 4);
const twenty = moment(sixteen).hours(sixteen.hour() + 4);
const tomorrow = moment(twenty).hours(twenty.hour() + 4);
console.log(today);
console.log(four);
console.log(eight);
console.log(twelve);
console.log(sixteen);
console.log(twenty);
console.log(tomorrow);
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.3/moment.min.js"></script>
What you want is then actually not adding 4 hours, but finding the next time where the hours are a multiple of 4.
So, remove all suggestion from your code that you are adding four hours (cf. your variable name).
You can do this:
const someday = moment(2374095600000);
console.log(someday.toString());
const hours = someday.hours();
someday.hours(hours + 4 - (hours % 4)); // Find next time that is multiple of 4.
console.log(someday.toString());
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.3/moment.min.js"></script>

How Can I use new Date().setHours(0,0,0) in a single line? [duplicate]

What is the simplest way to obtain an instance of new Date() but set the time at midnight?
The setHours method can take optional minutes, seconds and ms arguments, for example:
var d = new Date();
d.setHours(0,0,0,0);
That will set the time to 00:00:00.000 of your current timezone, if you want to work in UTC time, you can use the setUTCHours method.
Just wanted to clarify that the snippet from accepted answer gives the nearest midnight in the past:
var d = new Date();
d.setHours(0,0,0,0); // last midnight
If you want to get the nearest midnight in future, use the following code:
var d = new Date();
d.setHours(24,0,0,0); // next midnight
A one-liner for object configs:
new Date(new Date().setHours(0,0,0,0));
When creating an element:
dateFieldConfig = {
name: "mydate",
value: new Date(new Date().setHours(0, 0, 0, 0)),
}
Just going to add this here because I landed on this page looking for how to do this in moment.js and others may do too.
[Rationale: the word "moment" already appears elsewhere on this page so search engines direct here, and moment.js is widespread enough to warrant to being covered going on how often it is mentioned in other date-related SO questions]
So, in version 2.0.0 and above:
date.startOf('day');
For earlier versions:
date.sod();
Docs:
http://momentjs.com/docs/#/manipulating/start-of/
You can probably use
new Date().setUTCHours(0,0,0,0)
if you need the value only once.
If calculating with dates summertime will cause often 1 hour more or one hour less than midnight (CEST). This causes 1 day difference when dates return. So the dates have to round to the nearest midnight. So the code will be (thanks to jamisOn):
var d = new Date();
if(d.getHours() < 12) {
d.setHours(0,0,0,0); // previous midnight day
} else {
d.setHours(24,0,0,0); // next midnight day
}
Adding usefulness to #Dan's example, I had the need to find the next midday or midnight.
var d = new Date();
if(d.getHours() < 12) {
d.setHours(12,0,0,0); // next midnight/midday is midday
} else {
d.setHours(24,0,0,0); // next midnight/midday is midnight
}
This allowed me to set a frequency cap for an event, only allowing it to happen once in the morning and once in the afternoon for any visitor to my site. The date captured was used to set the expiration of the cookie.
I have made a couple prototypes to handle this for me.
// This is a safety check to make sure the prototype is not already defined.
Function.prototype.method = function (name, func) {
if (!this.prototype[name]) {
this.prototype[name] = func;
return this;
}
};
Date.method('endOfDay', function () {
var date = new Date(this);
date.setHours(23, 59, 59, 999);
return date;
});
Date.method('startOfDay', function () {
var date = new Date(this);
date.setHours(0, 0, 0, 0);
return date;
});
if you dont want the saftey check, then you can just use
Date.prototype.startOfDay = function(){
/*Method body here*/
};
Example usage:
var date = new Date($.now()); // $.now() requires jQuery
console.log('startOfDay: ' + date.startOfDay());
console.log('endOfDay: ' + date.endOfDay());
In case you already have d3.js as a dependency in your project, or don't mind bringing it in, d3-time (d3.js library is modular as of v4.0.0) has got Intervals.
They might prove useful when setting dates to "default" values, e.g. midnight, 0.00 seconds, the first of the month, etc.
var d = new Date(); // Wed Aug 02 2017 15:01:07 GMT+0200 (CEST)
d3.timeHour(d) // Wed Aug 02 2017 00:00:00 GMT+0200 (CEST)
d3.timeMonth(d) // Tue Aug 01 2017 00:00:00 GMT+0200 (CEST)
Using the dayjs library, you can use the startOf('day') method.
const dayjs = require('dayjs');
const todayAtMidnight= dayjs().startOf('day');
// Get as a native date object
console.log(todayAtMidnight.toDate());
To get the start of a particular day you can use the following:
const date = dayjs("2023-02-12").startOf('day');

Project date in Javascript

I have written some Javascript code that spits out an estimated time frame.
For example, right now, it's giving me: 646 days, 5 hours, 13 minutes
Given that info, if I create a new date in Javascript like:
var d = new Date();
How do I use the info to project the date in the future?
For example, today is June 30, 2018 and 646 days from now is April 6, 2020. So I'd want to calculate that on page load each time, because the projected date is constantly changing.
You have two choices, calculate it in total and add the number (as seen in one of post above), else you can do part by part, meaning day part, time part etc, this way you can write your own mini prototype functions to account for all or say most types of date complexities such as daylight savings etc etc. Just to give a fair idea, start with the date.
To do so use Date.prototype.setDate(), Date.prototype.setHours, Date.prototype.setMinutes()
var projectEndDate = new Date();
projectEndDate.setDate(today.getDate()+646);
// use Date.prototype.setHours(), then
// Date.prototype.setMinutes() and so on
Just add the time to today:
new Date( Date.now() + ((646 * 24 + 5) * 60 + 13) * 60 * 1000)
Or if you want to consider that not every day has 24 hours:
const date = new Date;
date.setDate(date.getDate() + 646);
date.setHours(date.getHours() + 5);
date.setMinutes(date.getMinutes() + 13);
Momentjs Is by far the best library to use for any date calculation.
let endDate = moment().add({
d:646, //days
h: 5, //hours
m: 13
}).format('MMMM D, YYYY')
document.write(endDate)
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.22.2/moment.js"></script>

Difference between two dates in hrs and mins

I have two dates in millis 1513885098821 & 1513885078742.
How to display the difference between above two dates in hrs and mins like 2 hrs 31 mins.
If moment have any option then its good, solution using plain javascript is also ok for me.
I tried below
moment(new Date(txn.toDate - txn.fromDate)).format('HH mm')
But it gives 05 30 result. Output of below line is
new Date(1513885098821 - 1513885078742);
result: Thu Jan 01 1970 05:30:20 GMT+0530 (India Standard Time)
There are probably countless answers already to help you find the difference between two dates, either using moment js or simply the native javascript Date object. Since you are having difficulty though, here is an example using moment js and its diff function:
// use timestamps to create moment objects
const startDate = moment.utc(1513885098821);
const endDate = moment.utc(1513885078742);
const hourDiff = startDate.diff(endDate, 'hours');
console.log(hourDiff); // 0
const minuteDiff = startDate.diff(endDate, 'minutes');
console.log(minuteDiff); // 0
const secondDiff = startDate.diff(endDate, 'seconds');
console.log(secondDiff); // 20
console.log(`${hourDiff}hrs ${minuteDiff}mins ${secondDiff}sec`); // 0hrs 0mins 20sec
Or try it online here.
You don't need to use Date, just do this:
prettyMillisDiff(millis1, millis2) {
let minDiff = (millis1 - millis2)/60000;
if (minDiff < 0) {
minDiff *= -1;
}
const hours = Math.floor(minDiff/60);
const mins = Math.floor(minDiff%60);
console.log(`${hours} hours ${mins} mins`);
}
try splitting string from the first method.
var k=moment(new Date(txn.toDate - txn.fromDate)).format('HH mm');
var frmt=k.split(' ');
var min=frmt+'mm';
var hr=frmt+'fr';

JavaScript setHours() and getHours() [duplicate]

I am trying to subtract hours from a given date time string using javascript.
My code is like:
var cbTime = new Date();
cbTime = selectedTime.setHours(-5.5);
Where selectedTime is the given time (time that i pass as parameter).
So suppose selectedTime is Tue Sep 16 19:15:16 UTC+0530 2014
Ans I get is : 1410875116995
I want answer in datetime format.
Am I doing something wrong here? Or there is some other solution?
The reason is that setHours(), setMinutes(), etc, take an Integer as a parameter. From the docs:
...
The setMinutes() method sets the minutes for a specified date
according to local time.
...
Parameters:
An integer between 0 and 59, representing the minutes.
So, you could do this:
var selectedTime = new Date(),
cbTime = new Date();
cbTime.setHours(selectedTime.getHours() - 5);
cbTime.setMinutes(selectedTime.getMinutes() - 30);
document.write('cbTime: ' + cbTime);
document.write('<br>');
document.write('selectedTime: ' + selectedTime);
Well first off setting the hours to -5.5 is nonsensical, the code will truncate to an integer (-5) and then take that as "five hours before midnight", which is 7PM yesterday.
Second, setHours (and other functions like it) modify the Date object (try console.log(cbTime)) and return the timestamp (number of milliseconds since the epoch).
You should not rely on the output format of the browser converting the Date object to a string for you, and should instead use get*() functions to format it yourself.
According to this:
http://www.w3schools.com/jsref/jsref_sethours.asp
You'll get "Milliseconds between the date object and midnight January 1 1970" as a return value of setHours.
Perhaps you're looking for this:
http://www.w3schools.com/jsref/tryit.asp?filename=tryjsref_sethours3
Edit:
If you want to subtract 5.5 hours, first you have to subtract 5 hours, then 30 minutes. Optionally you can convert 5.5 hours to 330 minutes and subtract them like this:
var d = new Date();
d.setMinutes(d.getMinutes() - 330);
document.getElementById("demo").innerHTML = d;
Use:
var cbTime = new Date();
cbTime.setHours(cbTime.getHours() - 5.5)
cbTime.toLocaleString();
try this:
var cbTime = new Date();
cbTime.setHours(cbTime.getHours() - 5.5)
cbTime.toLocaleString();

Categories