Issue317: Introducing Multiple Locale Support
Partially closes #317 

This branch introduces the following new formats (already in use in moment.js):

* LT
* LTS
* L
* LL
* LLL
* LLLL

These tokens define shortcuts to usual, local specific, formats. Example:

    dayjs().format('LL');   // August 29, 2018

It works for english, french and spanish. To add a new language, we just need to add the following object into the corresponding locale file. Example (src/locale/fr.js):
 
	  longDateFormat: {
	    LT: 'HH:mm',
	    LTS: 'HH:mm:ss',
	    L: 'DD/MM/YYYY',
	    LL: 'D MMMM YYYY',
	    LLL: 'D MMMM YYYY HH:mm',
	    LLLL: 'dddd D MMMM YYYY HH:mm'
	  }

Hello 😄
Are you considering adding something similar to the "Multiple Local support" of moment.js ?

    moment.locale();         // en
    moment().format('LT');   // 2:19 PM
    moment().format('LTS');  // 2:19:56 PM
    moment().format('L');    // 08/29/2018
    moment().format('l');    // 8/29/2018
    moment().format('LL');   // August 29, 2018
    moment().format('ll');   // Aug 29, 2018
    moment().format('LLL');  // August 29, 2018 2:19 PM
    moment().format('lll');  // Aug 29, 2018 2:19 PM
    moment().format('LLLL'); // Wednesday, August 29, 2018 2:19 PM

The idea is to keep the same tokens (LT, LTS, L...) and output different strings according to the language. My company needs this feature, so I am going to work on it, any advice/suggestions are welcome.
Feature request/Discussion: "Multiple Locale Support" like moment.js
diff --git a/src/constant.js b/src/constant.js
index 9b44afdaa..9e0b47072 100644
--- a/src/constant.js
+++ b/src/constant.js
@@ -25,7 +25,7 @@ export const FORMAT_DEFAULT = 'YYYY-MM-DDTHH:mm:ssZ'
 
 // regex
 export const REGEX_PARSE = /^(\d{4})-?(\d{1,2})-?(\d{0,2})(.*?(\d{1,2}):(\d{1,2}):(\d{1,2}))?.?(\d{1,3})?$/
-export const REGEX_FORMAT = /\[.*?\]|Y{2,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|SSS/g
+export const REGEX_FORMAT = /\[.*?\]|Y{2,4}|M{1,4}|D{1,2}|d{1,4}|H{1,2}|h{1,2}|a|A|m{1,2}|s{1,2}|Z{1,2}|(LTS|LT|LL?L?L?|l{1,4})|SSS/g
 
 export const en = {
   name: 'en',
diff --git a/src/index.js b/src/index.js
index e34a920ff..2c9c517b7 100644
--- a/src/index.js
+++ b/src/index.js
@@ -280,6 +280,19 @@ class Dayjs {
     const {
       weekdays, months
     } = locale
+
+    let { longDateFormat } = locale
+    if (longDateFormat === undefined) {
+      longDateFormat = {
+        LTS: 'h:mm:ss A',
+        LT: 'h:mm A',
+        L: 'MM/DD/YYYY',
+        LL: 'MMMM D, YYYY',
+        LLL: 'MMMM D, YYYY h:mm A',
+        LLLL: 'dddd, MMMM D, YYYY h:mm A'
+      }
+    }
+
     const getShort = (arr, index, full, length) => (
       (arr && arr[index]) || full[index].substr(0, length)
     )
@@ -334,6 +347,25 @@ class Dayjs {
           return Utils.padStart(this.$ms, 3, '0')
         case 'Z':
           return zoneStr
+
+        case 'LT':
+        case 'lt':
+          return this.format(longDateFormat.LT)
+        case 'LTS':
+        case 'lts':
+          return this.format(longDateFormat.LTS)
+        case 'L':
+        case 'l':
+          return this.format(longDateFormat.L)
+        case 'LL':
+        case 'll':
+          return this.format(longDateFormat.LL)
+        case 'LLL':
+        case 'lll':
+          return this.format(longDateFormat.LLL)
+        case 'LLLL':
+        case 'llll':
+          return this.format(longDateFormat.LLLL)
         default: // 'ZZ'
           return zoneStr.replace(':', '')
       }
diff --git a/src/locale/es.js b/src/locale/es.js
index 58312ea33..84959fb7e 100644
--- a/src/locale/es.js
+++ b/src/locale/es.js
@@ -19,7 +19,15 @@ const locale = {
     y: 'un año',
     yy: '%d años'
   },
-  ordinal: n => `${n}º`
+  ordinal: n => `${n}º`,
+  longDateFormat: {
+    LT: 'H:mm',
+    LTS: 'H:mm:ss',
+    L: 'DD/MM/YYYY',
+    LL: 'D [de] MMMM [de] YYYY',
+    LLL: 'D [de] MMMM [de] YYYY H:mm',
+    LLLL: 'dddd, D [de] MMMM [de] YYYY H:mm'
+  }
 }
 
 dayjs.locale(locale, null, true)
diff --git a/src/locale/fr.js b/src/locale/fr.js
index aebfc6701..bbbc1e9ab 100644
--- a/src/locale/fr.js
+++ b/src/locale/fr.js
@@ -19,7 +19,15 @@ const locale = {
     y: 'un an',
     yy: '%d ans'
   },
-  ordinal: n => `${n}º`
+  ordinal: n => `${n}º`,
+  longDateFormat: {
+    LT: 'HH:mm',
+    LTS: 'HH:mm:ss',
+    L: 'DD/MM/YYYY',
+    LL: 'D MMMM YYYY',
+    LLL: 'D MMMM YYYY HH:mm',
+    LLLL: 'dddd D MMMM YYYY HH:mm'
+  }
 }
 
 dayjs.locale(locale, null, true)

diff --git a/test/display.test.js b/test/display.test.js
index 29024b9f3..71fd70d81 100644
--- a/test/display.test.js
+++ b/test/display.test.js
@@ -2,6 +2,8 @@ import moment from 'moment'
 import MockDate from 'mockdate'
 import dayjs from '../src'
 import th from '../src/locale/th'
+import '../src/locale/fr'
+import '../src/locale/es'
 
 beforeEach(() => {
   MockDate.set(new Date())
@@ -114,6 +116,33 @@ it('Format Escaping characters', () => {
   expect(dayjs().format(string)).toBe(moment().format(string))
 })
 
+it('Format LTS LT L LL LLL LLLL', () => {
+  expect(dayjs().format('LTS')).toBe(moment().format('LTS'))
+  expect(dayjs().format('LT')).toBe(moment().format('LT'))
+  expect(dayjs().format('L')).toBe(moment().format('L'))
+  expect(dayjs().format('LL')).toBe(moment().format('LL'))
+  expect(dayjs().format('LLL')).toBe(moment().format('LLL'))
+  expect(dayjs().format('LLLL')).toBe(moment().format('LLLL'))
+})
+
+it('French LTS, LT, L, LL, LLL, LLLL', () => {
+  expect(dayjs().locale('fr').format('LTS')).toBe(moment().locale('fr').format('LTS'))
+  expect(dayjs().locale('fr').format('LT')).toBe(moment().locale('fr').format('LT'))
+  expect(dayjs().locale('fr').format('L').toLowerCase()).toBe(moment().locale('fr').format('L'))
+  expect(dayjs().locale('fr').format('LL').toLowerCase()).toBe(moment().locale('fr').format('LL'))
+  expect(dayjs().locale('fr').format('LLL').toLowerCase()).toBe(moment().locale('fr').format('LLL'))
+  expect(dayjs().locale('fr').format('LLLL').toLowerCase()).toBe(moment().locale('fr').format('LLLL'))
+})
+
+it('Spanish LTS, LT, L, LL, LLL, LLLL', () => {
+  expect(dayjs().locale('es').format('LTS')).toBe(moment().locale('es').format('LTS'))
+  expect(dayjs().locale('es').format('LT')).toBe(moment().locale('es').format('LT'))
+  expect(dayjs().locale('es').format('L')).toBe(moment().locale('es').format('L'))
+  expect(dayjs().locale('es').format('LL').toLowerCase()).toBe(moment().locale('es').format('LL').toLowerCase())
+  expect(dayjs().locale('es').format('LLL').toLowerCase()).toBe(moment().locale('es').format('LLL').toLowerCase())
+  expect(dayjs().locale('es').format('LLLL').toLowerCase()).toBe(moment().locale('es').format('LLLL').toLowerCase())
+})
+
 describe('Difference', () => {
   it('empty -> default milliseconds', () => {
     const dateString = '20110101'

{"test/display.test.js": {"run": "PASS", "test": "FAIL", "fix": "PASS"}}
{"test/plugin/isLeapYear.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/get-set.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/utils.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/relativeTime.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/parse.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/locale/keys.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/query.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/manipulate.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/advancedFormat.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/buddhistEra.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/weekOfYear.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}, "test/plugin/isBetween.test.js": {"run": "PASS", "test": "PASS", "fix": "PASS"}}
{"test/display.test.js": {"run": "PASS", "test": "FAIL", "fix": "PASS"}}
{"passed_count": 15, "failed_count": 0, "skipped_count": 0, "passed_tests": ["test/plugin/isLeapYear.test.js", "test/get-set.test.js", "test/locale.test.js", "test/utils.test.js", "test/plugin.test.js", "test/plugin/relativeTime.test.js", "test/parse.test.js", "test/locale/keys.test.js", "test/query.test.js", "test/manipulate.test.js", "test/plugin/advancedFormat.test.js", "test/plugin/buddhistEra.test.js", "test/display.test.js", "test/plugin/weekOfYear.test.js", "test/plugin/isBetween.test.js"], "failed_tests": [], "skipped_tests": []}
{"passed_count": 14, "failed_count": 1, "skipped_count": 0, "passed_tests": ["test/plugin.test.js", "test/get-set.test.js", "test/locale.test.js", "test/utils.test.js", "test/query.test.js", "test/plugin/relativeTime.test.js", "test/parse.test.js", "test/plugin/isLeapYear.test.js", "test/locale/keys.test.js", "test/plugin/advancedFormat.test.js", "test/plugin/buddhistEra.test.js", "test/manipulate.test.js", "test/plugin/weekOfYear.test.js", "test/plugin/isBetween.test.js"], "failed_tests": ["test/display.test.js"], "skipped_tests": []}
{"passed_count": 15, "failed_count": 0, "skipped_count": 0, "passed_tests": ["test/plugin.test.js", "test/get-set.test.js", "test/query.test.js", "test/utils.test.js", "test/locale.test.js", "test/plugin/relativeTime.test.js", "test/parse.test.js", "test/plugin/isLeapYear.test.js", "test/locale/keys.test.js", "test/plugin/buddhistEra.test.js", "test/manipulate.test.js", "test/plugin/advancedFormat.test.js", "test/display.test.js", "test/plugin/weekOfYear.test.js", "test/plugin/isBetween.test.js"], "failed_tests": [], "skipped_tests": []}