HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

HumanDate for easier date calculations

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
datecalculationshumandateforeasier

Problem

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().endOfTheWee

Solution

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.

Code Snippets

new HumanDate().day(-1).day()
if (numOfDays === undefined) {
    return date.getDate();
}
else {
    date.setDate(date.getDate() + numOfDays);
    return this;
}
if (numOfDays === undefined) {
    return date.getDate();
}

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

Context

StackExchange Code Review Q#140775, answer score: 2

Revisions (0)

No revisions yet.