views:

51

answers:

3

I'm working on a project where the user needs to provide time estimates on specific tasks. Im wondering if there's a script already out there ( like date.js ) that can take user input and parse it to number of seconds.

Examples: 
"2 days" = 172800
"2 hours" = 7200
"1d 5h" = 104400
"15 minutes" = 900

date.js is great for finding the specific date in the future, but I need the total number of seconds, not a specific end date.

I will code this myself if it doesn't already exist, just want to save some time if it's out there.

Thanks!

+3  A: 

Here's a library off the top of my head (sorry I couldn't resist)

var stringToSeconds = (function() {
  //Closure to define things that
  //do not change per function call

  var reg = /(\d+)\s*(\w+)/g;
  var units = {};

  //Lets be verbose
  units.seconds = 1;
  units.minutes = units.seconds * 60;
  units.hours = units.minutes * 60;
  units.days = units.hours * 24;
  units.weeks = units.days * 7;
  units.months = units.weeks * 4;
  units.years = units.months * 12;

  //Match unit shorthand
  var getUnit = function(unit) {
    unit = unit.toLowerCase();
    for (var name in units) {
      if (!units.hasOwnProperty(name)) continue;

      if (unit == name.substr(0, unit.length)) return units[name];
    }
    return 0;
  };


  return function(str) {
    var match, totalSeconds = 0;

    while (match = reg.exec(str)) {
      var num = match[1], unit = match[2];

      totalSeconds += getUnit(unit) * num;
    }

    return totalSeconds;
  }
}());

Try it out: http://jsbin.com/ozeda/2/edit

MooGoo
Very nice :) Works like a charm.
Pepper
It's rather difficult to convert from a number of seconds/minutes/hours/days/weeks into a number of months/years, because the number of days per month or per year is irregular and varies month-to-month and year-to-year.
Justice
Ya, i'm thinking about taking months and years out of the script when I put it into production. Not needed in my case.
Pepper
@Justice Yea I realized that but thought to put it in anyway for examples sake. Thinking about it again though, I might prefer to use the `new Date` constructor to build a future timestamp then subtract the current timestamp from it.
MooGoo
A: 

Made a change to the unit values, the calculation for months was messing up the years.

units.seconds = 1;
units.minutes = 60;
units.hours = 3600;
units.days = 86400;
units.weeks = 604800;
units.months = 262974383;
units.years = 31556926;
Pepper
A: 

Here is my final working version, based off of MooGoo's excellent script. Ill update this after some more bug/browser testing.

Please let me know if you have any improvements :)

  • added support for decimals. 1.5 hours = 1 hour 30 minutes
  • added get_string function. Pass in number of seconds and get a formatted string.
  • made it so the number defaults to hours. 5 = 5 hours

Demo: http://jsbin.com/ihuco3/2/edit

var string2seconds = {

  reg: /([\d]+[\.]?[\d{1,2}]?)\s*(\w+)/g,

  units: function()
  {
    var units = {};
    units.seconds = 1;
    units.minutes = 60;
    units.hours = 3600;
    units.days = 86400;
    units.weeks = 604800;
    units.months = 262974383;
    units.years = 31556926;
    return units;
  },

  get_unit: function(unit)
  {
    var units = this.units();

    unit = unit.toLowerCase();

    for (var name in units)
    {
      if( !units.hasOwnProperty(name) ) continue;
      if( unit == name.substr(0, unit.length) ) return units[name];
    }

    return 0;
  },

  get_string: function( seconds )
  {
    var years = Math.floor(seconds/31556926);
    var days = Math.floor((seconds % 31556926)/86400);
    var hours = Math.floor(((seconds % 31556926) % 86400) / 3600);
    var minutes = Math.floor((((seconds % 31556926) % 86400) % 3600 ) / 60);
    var string = '';

    if( years != 0 ) string = string + years + ' year'+this.s(years)+' ';
    if( days != 0 ) string = string + days + ' day'+this.s(days)+ ' ';
    if( hours != 0 ) string = string +  hours + ' hour'+this.s(hours)+ ' ';
    if( minutes != 0 ) string = string + minutes + ' minute'+this.s(minutes)+ ' ';

    if( string == '' ) return false;

    return string;
  },

  get_seconds: function( str )
  {
    var match, totalSeconds = 0, num, unit;

    if( (str - 0) == str && str.length > 0 )
    {
      str = str + 'hours';
    }

    while (match = this.reg.exec(str))
    {
      num = match[1];
      unit = match[2];
      totalSeconds += this.get_unit(unit) * num;
    }

    return totalSeconds;
  },

  s: function( count )
  {
    if( count != 1 ) return 's';
    return '';
  }

};
Pepper