12

I'm using Pikaday, which requires Moment.js to format dates. This allows easy date formatting:

var picker = new Pikaday({
  format: 'YYYY-MM-DD'
});

However, when I include the Pikaday npm package, Moment.js is over 40kb. Literally all I need it for is to change the date format to YYYY-MM-DD from the practically unusable default Pikaday format.

Can I do this without having to include a 40kb library?

Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
j_d
  • 2,818
  • 9
  • 50
  • 91

4 Answers4

13

If you want to use only format YYYY-MM-DD, you can build the date string using native Date methods:

const picker = new Pikaday({
  field: document.getElementById('datepicker')
 ,onSelect: date => {
    const year = date.getFullYear()
         ,month = date.getMonth() + 1
         ,day = date.getDate()
         ,formattedDate = [
            year
           ,month < 10 ? '0' + month : month
           ,day < 10 ? '0' + day : day
          ].join('-')
    document.getElementById('datepicker').value = formattedDate
  }
})

Demo

const picker = new Pikaday({
  field: document.getElementById('datepicker')
 ,onSelect: date => {
    const year = date.getFullYear()
         ,month = date.getMonth() + 1
         ,day = date.getDate()
         ,formattedDate = [
            year
           ,month < 10 ? '0' + month : month
           ,day < 10 ? '0' + day : day
          ].join('-')
    document.getElementById('datepicker').value = formattedDate
  }
})
@import url("https://rawgit.com/dbushell/Pikaday/master/css/pikaday.css");
<script src="https://rawgit.com/dbushell/Pikaday/master/pikaday.js"></script>
<input type="text" id="datepicker">
Michał Perłakowski
  • 88,409
  • 26
  • 156
  • 177
  • This is great. Only question left is how to have the datepicker input init like this, as this will only work once a selection is made... – j_d Apr 02 '16 at 15:37
  • @JohnDoe Why not just simply set the `value` attribute of the input element to the date you want? – Michał Perłakowski Apr 02 '16 at 15:41
  • If only it were that simple. Pikaday seems to reformat the value on initialisation. [Check out this fiddle to see what I mean](https://jsfiddle.net/mgno3etx/1/). – j_d Apr 02 '16 at 15:46
  • @JohnDoe Just specify the default date as `defaultDate` option when initializing Pikaday. See [this fiddle](https://jsfiddle.net/Gothdo/mgno3etx/3/). – Michał Perłakowski Apr 02 '16 at 15:54
  • Sure, but in my case that means taking an extra step to get that defaultDate value into js, as I'm using nunjucks to fill it into the HTML from a context. Guess this is the only way though. – j_d Apr 02 '16 at 16:11
  • But then, if you were to get the value from the inputfield, it's a string and then new Date(x) doesnt work anymore. So you would have to manually parse it again. Or am I missing something? – CharliesHeron Dec 08 '16 at 15:03
  • 2
    Just curious - is the way you did the commas in your answer a common way? Why not put the comma after the line it applies to, e.g. `const year = date.getFullYear(),`? – BruceWayne Aug 24 '18 at 15:40
  • 1
    @BruceWayne No, it's not very common. It's a part of [npm's coding style](https://docs.npmjs.com/misc/coding-style). The benefit of putting the comma first is that you can add another element without modifying the previous line, which results in cleaner Git diffs. However, now you can use [trailing commas](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Trailing_commas) to achieve the same result without making the code look weird. (1/2) – Michał Perłakowski Aug 24 '18 at 19:19
  • 1
    As for variable declarations, you can use one declaration per variable instead of one declaration with multiple comma-separated variables – that's how [Airbnb Style Guide does it](https://github.com/airbnb/javascript#variables--one-const). Because of that, I don't use npm's coding style anymore. (2/2) – Michał Perłakowski Aug 24 '18 at 19:19
2

I wrote a small formatter a while ago after seeing the date-formatter.js formatter and parser, maybe it will suit. It's pretty much self–documenting:

function formatDate(date, format) {
  var tokens = ['d',     // day number, e.g. 3, 12
                'dd',    // day number padded to two digits, e.g. 03, 12
                'ddd',   // day name abbreviated, e.g. Mon, Tue
                'dddd',  // day name in full, e.g. Monday, Tuesday
                'M',     // month number, e.g. 5, 10
                'MM',    // month number padded to two digits, e.g. 05, 10
                'MMM',   // month name abbreviated, e.g. May, Oct
                'MMMM',  // month name in full, e.g. May, October
                'y',     // Year, e.g. 71, 2011
                'yy',    // Year as two digits, e.g. 71, 11
                'yyy',   // Year as three digits, e.g. 071, 011
                'yyyy',  // Year padded to 4 digits, e.g. 0071, 2011
                'h',     // Hour, e.g. 1, 12
                'hh',    // Hour padded to two digits, e.g. 01, 12
                'm',     // Minute, e.g. 1, 23
                'mm',    // Minute padded to two digits, e.g. 01, 23
                's',     // Second, e.g. 1, 15
                'ss',    // Second padded to two digits, e.g. 01, 15
                'ap',    // 12 hour time lower case, e.g. 1:45 am, 12:30 pm
                'AP',    // 12 hour time upper case, e.g. 1:45 AM, 12:30 PM
                'z',     // Return values and "z" timezone
                'Z',     // Return values and "Z" timezone
                'tz',    // Append timezone as +/-00:00
                'TZ'];   // Append timezone as +/-00:00   
                
  var months = ['January','February','March','April','May','June','July',
                'August','September','October','November','December'];
                
  var days   = ['Sunday','Monday','Tuesday','Wednesday',
                'Thursday','Friday','Saturday'];
  
  // Generate all the parts as strings
  var parts = {d    : '' + date.getDate(),
               dd   : ('0' + date.getDate()).slice(-2),
               ddd  : days[date.getDay()].slice(0,3),
               dddd : days[date.getDay()],
               M    : '' + (date.getMonth() + 1),
               MM   : ('0' + (date.getMonth() + 1)).slice(-2),
               MMM  : months[date.getMonth()].slice(0,3),
               MMMM : months[date.getMonth()],
               y    : ''  + date.getFullYear(),
               yy   : ('0' + date.getFullYear()).slice(-2),
               yyy  : ('00' + date.getFullYear()).slice(-3),
               yyyy : ('000' + date.getFullYear()).slice(-4),
               h    : '' + date.getHours(),
               hh   : ('0' + date.getHours()).slice(-2),
               m    : '' + date.getMinutes(),
               mm   : ('0' + date.getMinutes()).slice(-2),
               s    : '' + date.getSeconds(),
               ss   : ('0' + date.getSeconds()).slice(-2)};

  // Parse format character by character and build string
  var b = format.split('');
  var formattedString = '';
  var token = '';
  for (var i = 0, iLen = b.length; i < iLen; i++) {
    token += b[i];
    if (tokens.indexOf(token + b[i+1]) == -1) {
      if (tokens.indexOf(token) != -1) {
        formattedString += parts[token];
      } else {
        formattedString += token;
      }
      token = '';      
    }
 // console.log(token + ' : ' + formattedString);     
  }
  return formattedString;
}

['yyyy-MM-ddThh:mm:ss',
 'yyyyMMTddhhmm',
 'dddd, d MMMM, yyyy at hh:mm:ss'
].forEach(function (s) {
  document.write('<br>' + formatDate(this, s));
}, new Date());
RobG
  • 142,382
  • 31
  • 172
  • 209
1

Try this if you're using /uglify or other compilers this might work better for you.

onSelect: function(date) {

//Format here   
}

Instead of

onSelect: date => {

//Format here 

}
0

you can also do the following

new Pikaday({
    field: document.getElementById('eDate'), 
    toString: function(date) {
        var parts = [('0'+date.getDate()).slice(-2), ('0'+(date.getMonth()+1)).slice(-2), date.getFullYear()];
        return parts.join("-");
    }
})

this will produce 18-07-1980. You can change from '-' to '/' by changing return parts.join("-"); and you can rearrange parts to apply mm/dd/yyyy via parts array

Nick Zulu
  • 333
  • 2
  • 10