1

I'm trying to parse, validate and re-format dates in an HTML form using moment.js. Because the website is being used internationally I want to reformat the dates in D MMM YYYY format (eg: 1 Apr 2018) to minimise any confusion once they've been entered.

The textboxes in my code are defined as follows:

<input type="text" class="txt-date" name="foo" />

And the JavaScript I've written to do the validation/re-formatting is as follows:

$(function () {

    console.log("initial locale: " + moment.locale());
    console.log("initial date format:= " + moment.localeData().longDateFormat('L'));

    var locale = window.navigator.userLanguage || window.navigator.language;
    console.log("changing locale to: " + locale);
    moment.locale(locale);

    console.log("updated locale: " + moment.locale());
    console.log("updated date format = " + moment.localeData().longDateFormat('L'));

    $('input.txt-date').on('change', function() {
        var v = $(this).val();
        if (!v) return; // No value in the textbox

        v = moment(v); // Parse the date
        if (!v.isValid) {
            alert("Invalid Date!");
            return;
        }

        // Re-format the date
        $(this).val(v.format("D MMM YYYY"));
    });
});

Here's the output in the browser's log:

initial locale = en

initial date format = MM/DD/YYYY

changing locale to: en-GB

updated locale: en

updated date format = MM/DD/YYYY

Essentially, moment.js seems to assume that I should be using English (US) regional settings, rather than English (UK). Changing the locale (as shown here) based on the user language seems to have made no difference.

All I want to do is to be able to parse date strings in either the user's local/regional format (or D MMM YYYY if they enter it that way). Can anyone provide any pointers?


Solution

Thanks to Phani for the help. In order to get this working you'll need to include the moment-with-locales.js file (which can be found at "https://momentjs.com/downloads/moment-with-locales.js" but is also included in the NuGet package).

The updated JavaScript is as follows:

$(function () {

    // Configure moment to use the user's locale
    moment.locale(window.navigator.userLanguage || window.navigator.language);

    $('input.txt-date').on('change', function () {
        var v = $(this).val();
        if (!v) return; // No value in the textbox

        // Parse the date specified
        var fmt = moment.localeData().longDateFormat('L');
        v = moment(v, [fmt, "D MMM YY", "D MMM YYYY"]);

        // If the date is invalid, warn the user
        if (!v.isValid()) {
            alert("Invalid Date!");
            return;
        }

        // Re-format the date
        $(this).val(v.format("D MMM YYYY"));
    });
});

This combination has worked with every valid date I've could throw at it.

Pete
  • 1,807
  • 1
  • 16
  • 32
  • 1
    Please don't edit the solution into the question; instead, add an answer below. – Mithical Sep 13 '17 at 13:25
  • 1
    It's a common enough way of rewarding the person who got me 90% the way there by flagging their response as an answer, whist displaying the final solution to my issue in such a manner that it won't be overlooked as a response that's not flagged as the answer. – Pete Sep 13 '17 at 13:41

1 Answers1

2

The issue is because of the moment locales missing or not imported. Once you import the locales, you can change the locale. You can find the moment locales imported from CDN (below).

Note that I have hardcoded the locale to en-gb as per your needs.

$(function () {          
 console.log(moment.locales())
 console.log("initial locale: " + moment.locale());
 console.log("initial date format:= " + moment.localeData().longDateFormat('L'));

 var locale = window.navigator.userLanguage || window.navigator.language;
 console.log("changing locale to: " + locale);
 moment.locale("en-gb");

 console.log("updated locale: " + moment.locale());
 console.log("updated date format = " + moment.localeData().longDateFormat('L'));

 $('input.txt-date').on('change', function () {
  var v = $(this).val();
  if (!v) return; // No value in the textbox

  v = moment(v); // Parse the date
  if (!v.isValid) {
   alert("Invalid Date!");
   return;
  }

  // Re-format the date
  $(this).val(v.format("D MMM YYYY"));
 });
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
 
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.18.1/moment.min.js"></script>

<!-- load all available momentjs locales -->
<script src="https://momentjs.com/downloads/moment-with-locales.js"></script>

<input type="text" class="txt-date" name="foo" />
Phani Kumar M
  • 4,564
  • 1
  • 14
  • 26
  • The addition of the locales file seems to fix the issue of the reported date format, which is now coming back correctly as DD/MM/YYYY. Unfortunately the parsing is still using US formatting - entering 01/09/2018 results in 09 Jan 2018, even though moment.locale() is reporting "en-gb" – Pete Sep 13 '17 at 13:12
  • Got it! I needed to add the formats to the moment(v) method. I'll put the solution in the question - thanks for your help! – Pete Sep 13 '17 at 13:17