Narcoleptic Pasta Manufacturer

    underscore.date

    0.6.1 • Public • Published

    Underscore.date

    Underscore.date is a javascript date library that helps create, manipulate, and format dates without extending the Date prototype.

    Author: Tim Wood

    Version: 0.6.1

    Note: There are some api changes that will break your code when upgrading from 0.4.1 to 0.5.0. Read about the changes in the changelog at the bottom of the page.

    1.8 kb (min + gzip)

    Where to use it

    Node.js

    Install with npm

    npm install underscore.date
    

    Usage

    var _date = require('underscore.date');
    console.log(_date('September 9 1999').fromNow());
    

    In the browser

    If underscore exists, underscore.date will mix itself into the underscore namespace, so you can use as you would use an underscore function.

    _.date('September 9 1999').fromNow();
    

    Otherwise, you should use _date.

    _date('September 9 1999').fromNow();
    

    _date()

    The library works by creating a _date() wrapper object. To create that wrapper, you can pass any of the following data types in.

    Number

    _date(1300291340510)
    

    An integer value representing the number of milliseconds since 1 January 1970 00:00:00 UTC.

    Date

    _date(new Date(2010, 1, 14, 15, 25, 50, 125))
    

    Any valid Date object. For more information on Date objects, see the JavaScript Date documentation at MDN

    Array

    _date([2010, 1, 14, 15, 25, 50, 125])
    

    An array mirroring the parameters passed into Date.UTC().

    [year, month = 0, date = 1, hours = 0, minutes = 0, seconds = 0, milliseconds = 0]

    Any value past the year is optional, and will default to the lowest possible number.

    undefined

    _date()
    

    If no value is passed to a 'dateInput' parameter, it will default to the current time using new Date().

    _date() === _date(new Date())
    

    String

    _date("Dec 25, 1995")
    

    A string that can be parsed by Date.parse().

    String with format

    _date("12-25-1995", "MM-DD-YYYY")
    

    A string and a format string. The second string will be used as the format to parse the first string.

    The format parts are similar to the formats from _date().format()

    Important: Parsing a string with a format is by far the slowest method of creating a date. If you have the ability to change the input, it is much faster (~15x) to use Unix timestamps.

    NOTE: The parser ignores non-alphanumeric characters, so both _date("12-25-1995", "MM-DD-YYYY") and _date("12\25\1995", "MM-DD-YYYY") will return the same thing.

    Input Output
    M or MM Month
    D or DD Day of month
    DDD or DDDD Day of year
    YY 2 digit year (if greater than 70, will return 1900's, else 2000's)
    YYYY 4 digit year
    a or A AM/PM
    H, HH, h, or hh 24 hour (for 12 hour time, use in conjunction with a or A)
    m or mm Minutes
    s or ss Seconds

    String with array of formats

    _date("12-25-1995", ["MM-DD-YYYY", "YYYY-MM-DD"])
    

    A list of format strings to try to parse the input string.

    This will find the format that is closest to the input formats. This is fundamentally problematic in cases like the following.

    _date("05-06-1995", ["MM-DD-YYYY", "DD-MM-YYYY"]) // June 5th or May 6th?
    

    Ideally, you should stick to one input format for creating dates.

    Important: THIS IS SLOW. This should only be used as a last line of defense. Check out the comparisons at http://jsperf.com/underscore-date/2 if you don't believe me. It's the one on the bar graph that you can't even see, that's how slow it is.

    _date Prototype

    underscore.date contains a number of utility functions for manipulating and formatting dates.

    _date.add()

    _date.add(object)
    

    Adds time per the object passed in.

    The object should have key value pairs as shown below.

    {
        ms : 200, // milliseconds
        s : 10,   // seconds
        m : 10,   // minutes (note: lowercase)
        h : 2,    // hours
        d : 3,    // days
        M : 2,    // months (note: uppercase)
        y : 3     // years
    }
    

    All the parameters are optional. Also, there are no upper limits for the values, so you can overload any of the parameters.

    { ms : 1000000 } // a million milliseconds
    { d : 360 }      // 360 days
    

    Special considerations for months and years

    If the day of the month on the original date is greater than the number of days in the final month, the day of the month will change to the last day in the final month.

    Example:

    _date([2010, 0, 31])              // January 31
    _date([2010, 0, 31]).add({M : 1}) // February 28
    

    _date.subtract()

    _date.subtract(object)
    

    Functions the same as _date.add(), only using subtraction instead of addition.

    Example:

    _date([2010, 1, 28])                 // February 28
    _date([2010, 1, 28]).subtract({M:1}) // January 28
    

    _date.format()

    _date.format(string)
    

    Returns a human readable string based on the format string that was passed in.

    var dateToFormat = new Date(2010, 1, 14, 15, 25, 50, 125);
    _date(dateToFormat).format("dddd, MMMM Do YYYY, h:mm:ss a"); // "Sunday, February 14th 2010, 3:25:50 pm"
    _date(dateToFormat).format("ddd, hA");                       // "Sun, 3PM"
    

    The formats are created by creating a string of replacable characters.

    Input Output
    Month
    M 1 2 ... 11 12
    Mo 1st 2nd ... 11th 12th
    MM 01 02 ... 11 12
    MMM Jan Feb ... Nov Dec
    MMMM January February ... November December
    Day of Month
    D 1 2 ... 30 30
    Do 1st 2nd ... 30th 31st
    DD 01 02 ... 30 31
    Day of Year
    DDD 1 2 ... 364 365
    DDDo 1st 2nd ... 364th 365th
    DDDD 001 002 ... 364 365
    Day of Week
    d 0 1 ... 5 6
    do 0th 1st ... 5th 6th
    ddd Sun Mon ... Fri Sat
    dddd Sunday Monday ... Friday Saturday
    Week of Year
    w 1 2 ... 52 53
    wo 1st 2nd ... 52nd 53rd
    ww 01 02 ... 52 53
    Year
    YY 70 71 ... 29 30
    YYYY 1970 1971 ... 2029 2030
    AM/PM
    A AM PM
    a am pm
    Hour
    H 0 1 ... 22 23
    HH 00 01 ... 22 23
    h 1 2 ... 11 12
    hh 01 02 ... 11 12
    Minute
    m 0 1 ... 58 59
    mm 00 01 ... 58 59
    Second
    s 0 1 ... 58 59
    ss 00 01 ... 58 59
    Timezone
    z EST CST ... MST PST
    zz Eastern Standard Time ... Pacific Standard Time

    NOTE: Internet Explorer uses a different implementation of Date.toString(), so we are unable to retrieve the full string of the timezone, and will fall back to 'z'.

    So:
    Firefox, Chrome, Safari, etc. == 'Eastern Standard Time'
    Internet Explorer, etc. == 'EST'

    _date.from()

    _date.from(date, withoutSuffix:boolean, asMilliseconds:boolean)
    

    Returns a string as relative time ('minutes ago', '5 months ago', etc).

    You can pass anything that you would pass to _date() as the first parameter, or a _date() object.

    _date([2007, 0, 29]).from(_date([2007, 0, 28])) // "a day ago"
    

    You can pass true as the second parameter to return without the prefixes and suffixes.

    _date([2007, 0, 29]).from(_date([2007, 0, 28]), true) // "a day"
    

    You can pass true as the third parameter to return as milliseconds. The number of milliseconds returned will be positive if the date passed in is later than the first date, and negative if the date passed in is earlier.

    _date([2007, 0, 29]).from(_date([2007, 0, 28]), true , true) // -86400000);
    _date([2007, 0, 27]).from(_date([2007, 0, 28]), true , true) // 86400000);
    

    The base strings for this function can be customized with _date.relativeTime.

    The breakdown of which string is displayed when is outlined in the table below.

    Range Key Sample Output
    0 to 45 seconds s seconds ago
    45 to 90 seconds m a minute ago
    90 seconds to 45 minutes mm 2 minutes ago ... 45 minutes ago
    45 to 90 minutes h an hour ago
    90 minutes to 22 hours hh 2 hours ago ... 22 hours ago
    22 to 36 hours d a day ago
    36 hours to 25 days dd 2 days ago ... 25 days ago
    25 to 45 days M a month ago
    45 to 345 days MM 2 months ago ... 11 months ago
    345 to 547 days (1.5 years) y a year ago
    548 days+ yy 2 years ago ... 20 years ago

    _date.fromNow()

    _date.fromNow(withoutSuffix:boolean, asMilliseconds:boolean)
    

    Retuns the time from now.

    A shortcut for _date.from(_date(), withoutSuffix:boolean, asMilliseconds:boolean).

    _date.isLeapYear()

    Returns true if the year is a leap year, false if it is not

    Examples :

    _date([2000]).isLeapYear() // true
    _date([2001]).isLeapYear() // false
    _date([2100]).isLeapYear() // false
    

    Localization and Customization

    _date.lang()

    Add or switch a language.

    To add a language, pass in the language key and the language constants. _date will cache the language based on the key for reuse.

    _date.lang('pt', {
        months : ["Janeiro", "Fevereiro", "Março", "Abril", "Maio", "Junho", "Julho", "Agosto", "Setembro", "Outubro", "Novembro", "Dezembro"],
        monthsShort : ["Jan", "Feb", "Mar", "Abr", "Mai", "Jun", "Jul", "Ago", "Set", "Out", "Nov", "Dez"],
        weekdays : ["Domingo", "Segunda-feira", "Terça-feira", "Quarta-feira", "Quinta-feira", "Sexta-feira", "Sábado"],
        weekdaysShort : ["Dom", "Seg", "Ter", "Qua", "Qui", "Sex", "Sáb"],
        relativeTime : {
            future: "em %s",
            past: "%s atrás",
            s: "segundos",
            m: "um minuto",
            mm: "%d minutos",
            h: "uma hora",
            hh: "%d horas",
            d: "um dia",
            dd: "%d dias",
            M: "um mês",
            MM: "%d meses",
            y: "um ano",
            yy: "%d anos"
        },
        ordinal : function (number) {
            return 'º';
        },
    }
    

    Once a language has been set, all _date.format and _date.from calls will use that language. To change to another language, call _date.lang('otherlang', { months : [] ... }).

    Once a language has been cached, you can simply call the key to retrieve it from the cache. This allows for easily switching between multiple languages.

    _date.lang('pt');
    _date(1316116057189).fromNow() // uma hora atrás
    _date.lang('en');
    _date(1316116057189).fromNow() // an hour ago
    

    There are languages in the ./underderscore.date.lang/ folder. You can require() them or add them to your page in the browser.

    Node

    var _date = require('underscore.date.js')
    var testLang = require('underscore.date.lang/test.js');
    _date.lang(testLang.abbr, testLang.lang);
    

    Browser

    <script src="underderscore.date.lang/leet.js"></script>
    

    NOTE: The language should be included after underscore.date, and will automatically switch to that language. To switch back to english, just use _date.lang('en') as that language is provided by default.

    Ad Hoc customization

    If you want to customize the wording of _date.format() and _date.from(), but don't want to create an entire language object, the strings are exposed through the _date object. You can modify these however you see fit. However, calls to _date.lang will overwrite them.

    Examples :

    _date.relativeTime.future = "%s from now";
    _date.relativeTime.past = "%s in the past";
    

    _date.relativeTime

    _date.relativeTime = {
        future: "in %s",
        past: "%s ago",
        s: "seconds",
        m: "a minute",
        mm: "%d minutes",
        h: "an hour",
        hh: "%d hours",
        d: "a day",
        dd: "%d days",
        M: "a month",
        MM: "%d months",
        y: "a year",
        yy: "%d years"
    };
    

    The strings used in _date.from().

    future and past are used as the suffixes/prefixes.

    For all these values, a single character refers to the singular, and an double character refers to the plural.

    _date.weekdays

    _date.weekdays = ["Sunday", "Monday", "Tuesday", "Wednesday", "Thursday", "Friday", "Saturday"];
    

    An array of day names, starting with Sunday.

    _date.weekdaysShort

    _date.weekdaysShort = ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"];
    

    An array of abbreviated day names, starting with Sunday.

    _date.months

    _date.months = ["January", "February", "March", "April", "May", "June", "July", "August", "September", "October", "November", "December"];
    

    An array of the names of the months, starting with January.

    _date.monthsShort

    _date.monthsShort = ["Jan", "Feb", "Mar", "Apr", "May", "Jun", "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"];
    

    An array of the abbreviated names of the months, starting with January.

    _date.ordinal

    _date.ordinal = function (number) {
        var b = number % 10;
        return (~~ (number % 100 / 10) === 1) ? 'th' : 
            (b === 1) ? 'st' : 
            (b === 2) ? 'nd' : 
            (b === 3) ? 'rd' : 'th';
    };
    

    A function that returns a string to be appended to the number passed in. More information on ordinal numbers

    Tests

    Unit tests

    Underscore.date unit tests

    Underscore.date performance tests

    The unit tests can also be run in node by running node test.js on the root folder.

    Speed tests

    Floor vs bitwiseor vs bitwisenor vs parseint

    Switch/case vs object of functions lookup

    Left zero filling

    Thanks to...

    The folks over at date.js.

    Everyone who helped with php.js date.

    Ryan McGeary for his work on the jQuery timeago plugin.

    License

    Underscore.date is freely distributable under the terms of the MIT license.

    Changelog

    0.6.1

    Added Portuguese, Italian, and French language support

    0.6.0

    Added _date.lang() support. Added support for passing multiple formats to try to parse a date. _date("07-10-1986", ["MM-DD-YYYY", "YYYY-MM-DD"]); Made parse from string and single format 25% faster.

    0.5.2

    Buxfix for issue 8 and issue 9.

    0.5.1

    Buxfix for issue 5.

    0.5.0

    Dropped the redundant _date.date() in favor of _date(). Removed _date.now(), as it is a duplicate of _date() with no parameters. Removed _date.isLeapYear(yearNuumber). Use _date([yearNumber]).isLeapYear() instead. Exposed customization options through the _date.relativeTime, _date.weekdays, _date.weekdaysShort, _date.months, _date.monthsShort, and _date.ordinal variables instead of the _date.customize() function.

    0.4.1

    Added date input formats for input strings.

    0.4.0

    Added underscore.date to npm. Removed dependancies on underscore.

    0.3.2

    Added 'z' and 'zz' to _.date().format(). Cleaned up some redundant code to trim off some bytes.

    0.3.1

    Cleaned up the namespace. Moved all date manipulation and display functions to the _.date() object.

    0.3.0

    Switched to the Underscore methodology of not mucking with the native objects' prototypes. Made chaining possible.

    0.2.1

    Changed date names to be a more pseudo standardized 'dddd, MMMM Do YYYY, h:mm:ss a'. Added Date.prototype functions add, subtract, isdst, and isleapyear.

    0.2.0

    Changed function names to be more concise. Changed date format from php date format to custom format.

    0.1.0

    Initial release

    Keywords

    none

    Install

    npm i underscore.date

    DownloadsWeekly Downloads

    63

    Version

    0.6.1

    License

    none

    Last publish

    Collaborators

    • timrwood