3
\$\begingroup\$

I need to calculate some dates like yesterday, this week/month, last three/ten days etc.

To make it a little bit easier and don't think about the Date weirdness all the time I created this helper:

var HumanDate = function() {

  var date = new Date();

  this.day = function(numOfDays) {
    if (numOfDays === undefined) {
        return date.getDate();
    }
    else {
        date.setDate(date.getDate() + numOfDays);
        return this;
    }
  };

  this.month = function(month) {
    if (month === undefined) {
      return date.getMonth() + 1;
    } 
    else {
      date.setMonth(date.getMonth() + month);
      return this;
    }
  };

  this.year = function() {
    return date.getFullYear();
  };

  this.dayOfWeek = function() {
        var dayOfWeek = date.getDay();
    return dayOfWeek === 0 ? dayOfWeek + 1 : dayOfWeek;
    };

  this.beginningOfTheWeek = function() {
    return this.day(-this.dayOfWeek() + 1);
  }

  this.endOfTheWeek = function() {
    return this.day(7 - this.dayOfWeek());
  }

  this.beginningOfTheMonth = function() {
    return this.day(-this.day() + 1);
  }

  this.endOfTheMonth = function() {
    return this.day(7 - this.dayOfWeek());
  }

  this.toJSDate = function(format) {
    return date;
  }

};

Examples:

console.log('day: ' + new HumanDate().day());
console.log('month: ' + new HumanDate().month());
console.log('year: ' + new HumanDate().year());
console.log('day of week: ' + new HumanDate().dayOfWeek());

console.log('yesterday: ' + new HumanDate().day(-1).day());
console.log('next month: ' + new HumanDate().month(1).toJSDate());
console.log('last month: ' + new HumanDate().month(-1).toJSDate());
console.log('beginning of the week: ' + new HumanDate().beginningOfTheWeek().toJSDate());
console.log('end of the week: ' + new HumanDate().endOfTheWeek().toJSDate());
console.log('beginning of the month: ' + new HumanDate().beginningOfTheMonth().toJSDate());
console.log('end of the week: ' + new HumanDate().endOfTheWeek().toJSDate());

Output:

day: 7
month: 9
year: 2016
day of week: 3
yesterday: 6
next month: Fri Oct 07 2016 20:04:50 GMT+0200 (W. Europe Summer Time)
last month: Sun Aug 07 2016 20:04:50 GMT+0200 (W. Europe Summer Time)
beginning of the week: Mon Sep 05 2016 20:04:50 GMT+0200 (W. Europe Summer Time)
end of the week: Sun Sep 11 2016 20:04:50 GMT+0200 (W. Europe Summer Time)
beginning of the month: Thu Sep 01 2016 20:04:50 GMT+0200 (W. Europe Summer Time)
end of the week: Sun Sep 11 2016 20:04:50 GMT+0200 (W. Europe Summer Time)

I need it for Google Sheets scripting & calculations so I'd rather not use an external library - (at least for now)

\$\endgroup\$
3
  • \$\begingroup\$ You pass a parameter "format" to your "toJSDate" method. But it isn't used. \$\endgroup\$ Sep 9, 2016 at 6:25
  • \$\begingroup\$ @mizech oh, I forgot to remove it after I realized that the js date cannot be formatted. \$\endgroup\$
    – t3chb0t
    Sep 9, 2016 at 6:26
  • 1
    \$\begingroup\$ No big issue. ;) But I thought I mention it. \$\endgroup\$ Sep 9, 2016 at 6:28

1 Answer 1

2
\$\begingroup\$

Some thoughts:

  • I find your method naming to be really confusing. To me, if I called methods named .day(), .month(), year(), etc. I would be expecting methods named in this manner to behave more like a getter than a setter.

For example, this usage seems very confusing:

new HumanDate().day(-1).day()

Consider naming like modifyDay(), modifyMonth(), etc.

  • You have unnecessary else conditions.

For example:

if (numOfDays === undefined) {
    return date.getDate();
}
else {
    date.setDate(date.getDate() + numOfDays);
    return this;
}

Could more clearly be written as:

if (numOfDays === undefined) {
    return date.getDate();
}

date.setDate(date.getDate() + numOfDays);
return this;    

Here there is no need for else since if returns.

  • The dayOfWeek() method looks odd. Why convert Sunday to Monday in all cases?
  • toJSDate() seems like an odd name for a function. The word "to" tends to connote cases where some casting or data transformation might take place. Here you are just returning the underlying date Object. Maybe just getDateObj() or something more descriptive of what is happening. Of course, the caller can always just access the .date property of the object to get the same result.
  • I think some of the logic you are applying to try force you week to start on a certain day, might best be something you want to specify in configuration on instantiation, or via more appropriate specificity around methods that deal with work week constructs. Just totally re-mapping the days returned by underlying Date object seems to sort of hide this away from the caller.
  • I think that perhaps you might need to look at the time component here as well. To me, if I am trying to get the beginning of a week or month, I would be expecting to get 00:00:00 as the time component. On the other hand, if maybe the methods were named something like modifyToBeginningOfMonth() perhaps the current behavior would be more expected.
  • Consider passing the Date object dependency in the constructor. Right now you limit this class to only working with Date object for current timestamp. If you took a Date object as parameter, you could set this Date object on your HumanDate object as is currently done, but allow the caller to fully utilize the capabilities of Date to set the timestamp to whatever they want to start with. This also makes the dependency of this class really clear.
  • You might give consideration to defining this class more as an extension of the underlying Date class. That way you can eliminate needing to wrap underlying date properties and methods.
\$\endgroup\$
10
  • \$\begingroup\$ my fist version was an extension to the Date.prototype but then I thoungt mhmm let's wrap it... I don't convert Sunday but Sunday 0 to 7, to me it's the 7th day of week, it's odd when it's the 0th - I cannot think this way :] the same with the month, the first the is the 0th but a day of month starts with a 0 - it's a total mindfuck with the dates in javascript - the idea was to not having to read the docs everytime I have to do something with the date. - I also think I should change the day(-1) to addDays(-1) or something like this. \$\endgroup\$
    – t3chb0t
    Sep 8, 2016 at 17:39
  • \$\begingroup\$ @t3chb0t extending the Date prototype is perhaps compelling for your use case, but certainly is not something to take lightly, as Date is not a true object in a javascript sense, so you in essence have to instantiate it and then transform it to a HumanDate object, which is a little unusual. Regarding zero-based dates. It is common through many languages, so just something I would encourage you to embrace rather than making these transformations just for your "readability". You are introducing unnecessary complexity in doing that. \$\endgroup\$
    – Mike Brant
    Sep 8, 2016 at 17:44
  • \$\begingroup\$ @t3chb0t Also, your dayOfWeek function, does not do what you think it does. It is only changing 0 to 1, not adding 1 to the underlying day of week value by 1 in all cases. \$\endgroup\$
    – Mike Brant
    Sep 8, 2016 at 17:46
  • \$\begingroup\$ ...and of course day is a day of week, but day of month is date :-| I've never seen such a mess before ;-] \$\endgroup\$
    – t3chb0t
    Sep 8, 2016 at 17:46
  • \$\begingroup\$ thx, then I have a bug there that I haven't found yet :-( \$\endgroup\$
    – t3chb0t
    Sep 8, 2016 at 17:47

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.