200

How can I translate this pseudo code into working JS [don't worry about where the end date comes from except that it's a valid JavaScript date].

var myEndDateTime = somedate;  //somedate is a valid JS date  
var durationInMinutes = 100; //this can be any number of minutes from 1-7200 (5 days)

//this is the calculation I don't know how to do
var myStartDate = somedate - durationInMinutes;

alert("The event will start on " + myStartDate.toDateString() + " at " + myStartDate.toTimeString());
halfer
  • 19,824
  • 17
  • 99
  • 186
brendan
  • 29,308
  • 20
  • 68
  • 109

9 Answers9

264

Once you know this:

  • You can create a Date by calling the constructor with milliseconds since Jan 1, 1970.
  • The valueOf() a Date is the number of milliseconds since Jan 1, 1970
  • There are 60,000 milliseconds in a minute :-]

In the code below, a new Date is created by subtracting the appropriate number of milliseconds from myEndDateTime:

var MS_PER_MINUTE = 60000;
var myStartDate = new Date(myEndDateTime - durationInMinutes * MS_PER_MINUTE);
Manu Artero
  • 9,238
  • 6
  • 58
  • 73
Daniel LeCheminant
  • 50,583
  • 16
  • 120
  • 115
  • 13
    But doesn't handle when you add minutes. To correctly handle when you add minutes, you should use `.getTime()`. Example: `var myStartDate = new Date(myEndDateTime.getTime() + durationInMinutes * MS_PER_MINUTE);` – Gabriel L. Oliveira May 12 '16 at 19:03
  • You can also use `var myStartDate = somedate.addMinutes(-durationInMuntes);` I assume somedate is a Date object – kubahaha Sep 09 '16 at 11:08
  • 1
    It works...but have a question that the Date() constructor have 3 options, i.e 1 : empty 2: string and 3: Number year, Number Month.... so the one being used above follows which constructor? – Zafar Mar 31 '17 at 20:31
  • 5
    [More falsehoods programmers believe about time, #32](http://infiniteundo.com/post/25509354022/more-falsehoods-programmers-believe-about-time) "There are 60 seconds in every minute." – Niet the Dark Absol Nov 04 '17 at 12:00
  • 1
    For an example of how this can go wrong, using Europe/London as the timezone locale: `var d = new Date("2017-10-29 01:50:00"), e = new Date(d.getTime() + 20 * 60000);` you would expect `e` to be `02:10:00`, right? Nope. `01:10:00`. DST says hi. And then there's leap-seconds... – Niet the Dark Absol Nov 04 '17 at 12:05
  • @NiettheDarkAbsol , this is correct, if you was needed to know the time after 20 minutes. – Viktor Mukhachev Sep 30 '20 at 14:21
  • @NiettheDarkAbsol, most time systems use 60 seconds in every minute, since "leap seconds" are unpredictable and extremely rare (0.000001% of seconds are leap-seconds). For example, Unix time 946684800 is 2020-01-01T00:00:00Z, even though there were 946684822 real seconds between 1970 and 2000. Such anomalies are easily smeared out and usually irrelevant, therefore most computer systems don't include them. – Paul Draper May 29 '23 at 20:35
133

You can also use get and set minutes to achieve it:

var endDate = somedate;

var startdate = new Date(endDate);

var durationInMinutes = 20;

startdate.setMinutes(endDate.getMinutes() - durationInMinutes);
Miquel
  • 4,741
  • 3
  • 20
  • 19
  • 88
    it's worth noting that `setMinutes()` is smart enough to handle negative minutes correctly. So if start date was 3:05, and you want to subtract 30 minutes, you'd be passing in `-25` to setMinutes(), which is smart enough to know that `3:-25` is `2:35`. (i.e. it doesn't throw an exception.) – Kip Aug 29 '11 at 17:43
  • 3
    @Kip - Thanks, that is the insight that makes this answer worthwhile. But do all browsers guarantee this? I ask because MDN says only 0 - 59 are allowed - but I suspect the docs are just wrong in this case? See: https://developer.mozilla.org/en/JavaScript/Reference/Global_Objects/Date/setMinutes – Justin Ethier Jan 13 '12 at 18:34
  • This was more useful to me, I wanted to subtract the time from an existing Date object instance that was set up in a particular way through the constructor. Thank you! – Bill Effin Murray Oct 20 '12 at 02:24
  • 1
    Just remember that `.setMinutes(...)` force handle `int` values. If you set `1.5 minutes` into a `Date` it'll only set `1 minute` and keep the seconds the same as before. – Gabriel L. Oliveira May 12 '16 at 18:50
  • I was getting wrong values in a similar use case when I tried startDate = endDate. Looks like the problem where a shallow copy happens – S Raghav Apr 23 '17 at 07:01
  • @raghav710, Date object is a reference type value in JavaScript – Viktor Mukhachev Sep 30 '20 at 14:30
  • this answer may not work well near timezone transition points, please consider to use getUTCMinutes/setUTCMinutes instead – Viktor Mukhachev Sep 30 '20 at 14:31
81

It's just ticks

Ticks mean milliseconds since Jan 1st, 1970 at 0:0:0 UTC. The date constructor can take in a number as a single argument which is interpreted as ticks.

When working with number of milliseconds/seconds/hours/days/weeks (static quantities), you can do things like this

const aMinuteAgo = new Date( Date.now() - 1000 * 60 );

or

const aMinuteLess = new Date( someDate.getTime() - 1000 * 60 );

then let JavaScript display the date and worry about what day of the week it is or what day of the month and year etc. You can choose to localize it or internationalize it natively with Intl.

I recommend using luxon for JavaScript related projects when you are doing anything more complicated than the above mentioned that requires arbitrary timezones or leap years or days of the month etc.

King Friday
  • 25,132
  • 12
  • 90
  • 84
  • 2
    IMO this is not that simple. It takes some effort to decrypt what this code actually does. The better approach is to wrap that kind of logic in a function. – sszarek Sep 01 '17 at 11:30
  • 3
    var aMinuteAgo = () => new Date( Date.now() - 1000 * 60 ); done – King Friday Jan 26 '22 at 04:26
16

moment.js has some really nice convenience methods to manipulate date objects

The .subtract method, allows you to subtract a certain amount of time units from a date, by providing the amount and a timeunit string.

var now = new Date();
// Sun Jan 22 2017 17:12:18 GMT+0200 ...
var olderDate = moment(now).subtract(3, 'minutes').toDate();
// Sun Jan 22 2017 17:09:18 GMT+0200 ...

Luxon also has an API to manipulate it's own DateTime object

var dt = DateTime.now(); 
// "1982-05-25T00:00:00.000Z"
dt.minus({ minutes: 3 });
dt.toISO();              
// "1982-05-24T23:57:00.000Z"
svarog
  • 9,477
  • 4
  • 61
  • 77
10

This is what I found:

//First, start with a particular time
var date = new Date();

//Add two hours
var dd = date.setHours(date.getHours() + 2);

//Go back 3 days
var dd = date.setDate(date.getDate() - 3);

//One minute ago...
var dd = date.setMinutes(date.getMinutes() - 1);

//Display the date:
var monthNames = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
var date = new Date(dd);
var day = date.getDate();
var monthIndex = date.getMonth();
var year = date.getFullYear();
var displayDate = monthNames[monthIndex] + ' ' + day + ', ' + year;
alert('Date is now: ' + displayDate);

Sources:

http://www.javascriptcookbook.com/article/Perform-date-manipulations-based-on-adding-or-subtracting-time/

https://stackoverflow.com/a/12798270/1873386

Community
  • 1
  • 1
crashwap
  • 2,846
  • 3
  • 28
  • 62
8
var date=new Date();

//here I am using "-30" to subtract 30 minutes from the current time.
var minute=date.setMinutes(date.getMinutes()-30); 

console.log(minute) //it will print the time and date according to the above condition in Unix-timestamp format.

you can convert Unix timestamp into conventional time by using new Date().for example

var extract=new Date(minute)
console.log(minute)//this will print the time in the readable format.
adiga
  • 34,372
  • 9
  • 61
  • 83
6

Try as below:

var dt = new Date();
dt.setMinutes( dt.getMinutes() - 20 );
console.log('#####',dt);
Jitendra
  • 3,135
  • 2
  • 26
  • 42
1

This is what I did: see on Codepen

var somedate = 1473888180593;
var myStartDate;
//var myStartDate = somedate - durationInMuntes;

myStartDate = new Date(dateAfterSubtracted('minutes', 100));

alert("The event will start on " + myStartDate.toDateString() + " at " + myStartDate.toTimeString());

function dateAfterSubtracted(range, amount){
    var now = new Date();
    if(range === 'years'){
        return now.setDate(now.getYear() - amount);
    }
    if(range === 'months'){
        return now.setDate(now.getMonth() - amount);
    }
    if(range === 'days'){
        return now.setDate(now.getDate() - amount);
    }
    if(range === 'hours'){
        return now.setDate(now.getHours() - amount);
    }
    if(range === 'minutes'){
        return now.setDate(now.getMinutes() - amount);
    }
    else {
        return null;
    }
}
Ronnie Royston
  • 16,778
  • 6
  • 77
  • 91
  • OP don't use `new Date()`, but has some specified date, and asked only about subtracting minutes. Also, your code doesn't work - it returns UNIX timestamp instead of Date object. – Michał Perłakowski Dec 29 '15 at 19:45
1

Extend Date class with this function

// Add (or substract if value is negative) the value, expresed in timeUnit
// to the date and return the new date.
Date.dateAdd = function(currentDate, value, timeUnit) {

    timeUnit = timeUnit.toLowerCase();
    var multiplyBy = { w:604800000,
                     d:86400000,
                     h:3600000,
                     m:60000,
                     s:1000 };
    var updatedDate = new Date(currentDate.getTime() + multiplyBy[timeUnit] * value);

    return updatedDate;
};

So you can add or substract a number of minutes, seconds, hours, days... to any date.

add_10_minutes_to_current_date = Date.dateAdd( Date(), 10, "m");
subs_1_hour_to_a_date = Date.dateAdd( date_value, -1, "h");
Gonzalo Cao
  • 2,286
  • 1
  • 24
  • 20