diff --git a/packages/utilities/psammead-locales/CHANGELOG.md b/packages/utilities/psammead-locales/CHANGELOG.md
index 8a7a6f437e..9f2c4d7ea7 100644
--- a/packages/utilities/psammead-locales/CHANGELOG.md
+++ b/packages/utilities/psammead-locales/CHANGELOG.md
@@ -3,6 +3,7 @@
| Version | Description |
| ------- | ----------- |
+| 2.7.0 | [PR#2114](https://github.com/bbc/psammead/pull/2114) Add some overrides for Brasil, Russian, Serbian and Ukrainian |
| 2.6.0 | [PR#2124](https://github.com/bbc/psammead/pull/2124) Add `ta` (Tamil) locale |
| 2.5.0 | [PR#2118](https://github.com/bbc/psammead/pull/2118) Add `mr` (Marathi) locale |
| 2.4.0 | [PR#2110](https://github.com/bbc/psammead/pull/2110) Add `hi` (Hindi) locale |
diff --git a/packages/utilities/psammead-locales/README.md b/packages/utilities/psammead-locales/README.md
index 92f2434a50..ff505173d1 100644
--- a/packages/utilities/psammead-locales/README.md
+++ b/packages/utilities/psammead-locales/README.md
@@ -16,6 +16,11 @@ The following locales have overrides to meet BBC World Service requirements wher
- `/moment/ar` - locale override for Arabic
- `/moment/fa` - locale override for Persian (Farsi)
+- `/moment/pt-br` - locale override for Brasil
+- `/moment/ru` - locale override for Russian
+- `/moment/sr` - locale override for Serbian
+- `/moment/sr-cyrl` - locale override for Serbian Cyrillic
+- `/moment/uk` - locale override for Ukrainian
- `/moment/yo` - locale override for Yoruba
- `/moment/ta` - locale override for Tamil
- `/moment/mr` - locale override for Marathi
diff --git a/packages/utilities/psammead-locales/moment/index.stories.jsx b/packages/utilities/psammead-locales/moment/index.stories.jsx
index 88b04e3f8f..b9b2070f5f 100644
--- a/packages/utilities/psammead-locales/moment/index.stories.jsx
+++ b/packages/utilities/psammead-locales/moment/index.stories.jsx
@@ -12,28 +12,38 @@ import { GEL_FF_REITH_SANS } from '@bbc/gel-foundations/typography';
import notes from '../README.md';
import './ar';
import './fa';
+import './hi';
import './ig';
+import './mr';
+import './pa-in';
import './pcm';
import './ps';
-import './yo';
-import './pa-in';
+import './pt-br';
+import './ru';
+import './sr';
+import './sr-cyrl';
import './ta';
-import './mr';
-import './hi';
+import './uk';
+import './yo';
const stories = storiesOf('Utilities|Psammead Locales', module);
const locales = [
{ name: 'Arabic', locale: 'ar' },
+ { name: 'Brasil', locale: 'pt-br' },
+ { name: 'Hindi', locale: 'hi' },
{ name: 'Igbo', locale: 'ig' },
+ { name: 'Marathi', locale: 'mr' },
{ name: 'Pashto', locale: 'ps' },
{ name: 'Persian', locale: 'fa' },
{ name: 'Pidgin', locale: 'pcm' },
- { name: 'Yoruba', locale: 'yo' },
{ name: 'Punjabi', locale: 'pa-in' },
+ { name: 'Russian', locale: 'ru' },
+ { name: 'Serbian', locale: 'sr' },
+ { name: 'Serbian Cyrillic', locale: 'sr-cyrl' },
{ name: 'Tamil', locale: 'ta' },
- { name: 'Marathi', locale: 'mr' },
- { name: 'Hindi', locale: 'hi' },
+ { name: 'Ukrainian', locale: 'uk' },
+ { name: 'Yoruba', locale: 'yo' },
];
// Fixed timestamp for 27 August 2019, 14:54 BST
diff --git a/packages/utilities/psammead-locales/moment/pt-br.js b/packages/utilities/psammead-locales/moment/pt-br.js
new file mode 100644
index 0000000000..175a21507b
--- /dev/null
+++ b/packages/utilities/psammead-locales/moment/pt-br.js
@@ -0,0 +1,10 @@
+var moment = require('moment');
+require('moment/locale/pt-br');
+
+moment.updateLocale('pt-br', {
+ longDateFormat: {
+ LL: 'D MMMM YYYY',
+ LLL: 'D MMMM YYYY [às] HH:mm',
+ LLLL: 'dddd, D MMMM YYYY [às] HH:mm',
+ },
+});
diff --git a/packages/utilities/psammead-locales/moment/pt-br.test.js b/packages/utilities/psammead-locales/moment/pt-br.test.js
new file mode 100644
index 0000000000..84650d0345
--- /dev/null
+++ b/packages/utilities/psammead-locales/moment/pt-br.test.js
@@ -0,0 +1,483 @@
+import moment from 'moment';
+import './pt-br';
+
+moment.locale('pt-br');
+
+// This asset overrides the gunit assertion done in the moment codebase.
+// Format and styling of this file has been keep consistent with the official moment tests.
+// An example of these tests can be seen at https://github.com/moment/moment/blob/develop/src/test/locale/en-gb.js
+const assert = { equal: (val1, val2) => expect(val1).toEqual(val2) };
+
+test('parse', function() {
+ var tests = 'Janeiro Jan_Fevereiro Fev_Março Mar_Abril Abr_Maio Mai_Junho Jun_Julho Jul_Agosto Ago_Setembro Set_Outubro Out_Novembro Nov_Dezembro Dez'.split(
+ '_'
+ ),
+ i;
+
+ function equalTest(input, mmm, i) {
+ assert.equal(
+ moment(input, mmm).month(),
+ i,
+ input + ' should be month ' + (i + 1)
+ );
+ }
+
+ for (i = 0; i < 12; i++) {
+ tests[i] = tests[i].split(' ');
+ equalTest(tests[i][0], 'MMM', i);
+ equalTest(tests[i][1], 'MMM', i);
+ equalTest(tests[i][0], 'MMMM', i);
+ equalTest(tests[i][1], 'MMMM', i);
+ equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i);
+ equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i);
+ equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i);
+ equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i);
+ }
+});
+
+test('format', function() {
+ var a = [
+ [
+ 'dddd, MMMM Do YYYY, h:mm:ss a',
+ 'Domingo, Fevereiro 14º 2010, 3:25:50 pm',
+ ],
+ ['ddd, hA', 'Dom, 3PM'],
+ ['M Mo MM MMMM MMM', '2 2º 02 Fevereiro Fev'],
+ ['YYYY YY', '2010 10'],
+ ['D Do DD', '14 14º 14'],
+ ['d do dddd ddd', '0 0º Domingo Dom'],
+ ['DDD DDDo DDDD', '45 45º 045'],
+ ['w wo ww', '8 8º 08'],
+ ['h hh', '3 03'],
+ ['H HH', '15 15'],
+ ['m mm', '25 25'],
+ ['s ss', '50 50'],
+ ['a A', 'pm PM'],
+ ['[the] DDDo [day of the year]', 'the 45º day of the year'],
+ ['LTS', '15:25:50'],
+ ['L', '14/02/2010'],
+ ['LL', '14 Fevereiro 2010'],
+ ['LLL', '14 Fevereiro 2010 às 15:25'],
+ ['LLLL', 'Domingo, 14 Fevereiro 2010 às 15:25'],
+ ['l', '14/2/2010'],
+ ['ll', '14 Fev 2010'],
+ ['lll', '14 Fev 2010 às 15:25'],
+ ['llll', 'Dom, 14 Fev 2010 às 15:25'],
+ ],
+ b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)),
+ i;
+ for (i = 0; i < a.length; i++) {
+ assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]);
+ }
+});
+
+test('format ordinal', function() {
+ assert.equal(moment([2011, 0, 1]).format('DDDo'), '1º', '1º');
+ assert.equal(moment([2011, 0, 2]).format('DDDo'), '2º', '2º');
+ assert.equal(moment([2011, 0, 3]).format('DDDo'), '3º', '3º');
+ assert.equal(moment([2011, 0, 4]).format('DDDo'), '4º', '4º');
+ assert.equal(moment([2011, 0, 5]).format('DDDo'), '5º', '5º');
+ assert.equal(moment([2011, 0, 6]).format('DDDo'), '6º', '6º');
+ assert.equal(moment([2011, 0, 7]).format('DDDo'), '7º', '7º');
+ assert.equal(moment([2011, 0, 8]).format('DDDo'), '8º', '8º');
+ assert.equal(moment([2011, 0, 9]).format('DDDo'), '9º', '9º');
+ assert.equal(moment([2011, 0, 10]).format('DDDo'), '10º', '10º');
+
+ assert.equal(moment([2011, 0, 11]).format('DDDo'), '11º', '11º');
+ assert.equal(moment([2011, 0, 12]).format('DDDo'), '12º', '12º');
+ assert.equal(moment([2011, 0, 13]).format('DDDo'), '13º', '13º');
+ assert.equal(moment([2011, 0, 14]).format('DDDo'), '14º', '14º');
+ assert.equal(moment([2011, 0, 15]).format('DDDo'), '15º', '15º');
+ assert.equal(moment([2011, 0, 16]).format('DDDo'), '16º', '16º');
+ assert.equal(moment([2011, 0, 17]).format('DDDo'), '17º', '17º');
+ assert.equal(moment([2011, 0, 18]).format('DDDo'), '18º', '18º');
+ assert.equal(moment([2011, 0, 19]).format('DDDo'), '19º', '19º');
+ assert.equal(moment([2011, 0, 20]).format('DDDo'), '20º', '20º');
+
+ assert.equal(moment([2011, 0, 21]).format('DDDo'), '21º', '21º');
+ assert.equal(moment([2011, 0, 22]).format('DDDo'), '22º', '22º');
+ assert.equal(moment([2011, 0, 23]).format('DDDo'), '23º', '23º');
+ assert.equal(moment([2011, 0, 24]).format('DDDo'), '24º', '24º');
+ assert.equal(moment([2011, 0, 25]).format('DDDo'), '25º', '25º');
+ assert.equal(moment([2011, 0, 26]).format('DDDo'), '26º', '26º');
+ assert.equal(moment([2011, 0, 27]).format('DDDo'), '27º', '27º');
+ assert.equal(moment([2011, 0, 28]).format('DDDo'), '28º', '28º');
+ assert.equal(moment([2011, 0, 29]).format('DDDo'), '29º', '29º');
+ assert.equal(moment([2011, 0, 30]).format('DDDo'), '30º', '30º');
+
+ assert.equal(moment([2011, 0, 31]).format('DDDo'), '31º', '31º');
+});
+
+test('format month', function() {
+ var expected = 'Janeiro Jan_Fevereiro Fev_Março Mar_Abril Abr_Maio Mai_Junho Jun_Julho Jul_Agosto Ago_Setembro Set_Outubro Out_Novembro Nov_Dezembro Dez'.split(
+ '_'
+ ),
+ i;
+ for (i = 0; i < expected.length; i++) {
+ assert.equal(
+ moment([2011, i, 1]).format('MMMM MMM'),
+ expected[i],
+ expected[i]
+ );
+ }
+});
+
+test('format week', function() {
+ var expected = 'Domingo Dom Do_Segunda-feira Seg 2ª_Terça-feira Ter 3ª_Quarta-feira Qua 4ª_Quinta-feira Qui 5ª_Sexta-feira Sex 6ª_Sábado Sáb Sá'.split(
+ '_'
+ ),
+ i;
+ for (i = 0; i < expected.length; i++) {
+ assert.equal(
+ moment([2011, 0, 2 + i]).format('dddd ddd dd'),
+ expected[i],
+ expected[i]
+ );
+ }
+});
+
+test('from', function() {
+ var start = moment([2007, 1, 28]);
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 44 }), true),
+ 'poucos segundos',
+ '44 seconds = seconds'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 45 }), true),
+ 'um minuto',
+ '45 seconds = a minute'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 89 }), true),
+ 'um minuto',
+ '89 seconds = a minute'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 90 }), true),
+ '2 minutos',
+ '90 seconds = 2 minutes'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 44 }), true),
+ '44 minutos',
+ '44 minutes = 44 minutes'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 45 }), true),
+ 'uma hora',
+ '45 minutes = an hour'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 89 }), true),
+ 'uma hora',
+ '89 minutes = an hour'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 90 }), true),
+ '2 horas',
+ '90 minutes = 2 hours'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 5 }), true),
+ '5 horas',
+ '5 hours = 5 hours'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 21 }), true),
+ '21 horas',
+ '21 hours = 21 hours'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 22 }), true),
+ 'um dia',
+ '22 hours = a day'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 35 }), true),
+ 'um dia',
+ '35 hours = a day'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 36 }), true),
+ '2 dias',
+ '36 hours = 2 days'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 1 }), true),
+ 'um dia',
+ '1 day = a day'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 5 }), true),
+ '5 dias',
+ '5 days = 5 days'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 25 }), true),
+ '25 dias',
+ '25 days = 25 days'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 26 }), true),
+ 'um mês',
+ '26 days = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 30 }), true),
+ 'um mês',
+ '30 days = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 43 }), true),
+ 'um mês',
+ '43 days = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 46 }), true),
+ '2 meses',
+ '46 days = 2 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 74 }), true),
+ '2 meses',
+ '75 days = 2 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 76 }), true),
+ '3 meses',
+ '76 days = 3 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ M: 1 }), true),
+ 'um mês',
+ '1 month = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ M: 5 }), true),
+ '5 meses',
+ '5 months = 5 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 345 }), true),
+ 'um ano',
+ '345 days = a year'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 548 }), true),
+ '2 anos',
+ '548 days = 2 years'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ y: 1 }), true),
+ 'um ano',
+ '1 year = a year'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ y: 5 }), true),
+ '5 anos',
+ '5 years = 5 years'
+ );
+});
+
+test('suffix', function() {
+ assert.equal(moment(30000).from(0), 'em poucos segundos', 'prefix');
+ assert.equal(moment(0).from(30000), 'há poucos segundos', 'prefix');
+});
+
+test('fromNow', function() {
+ assert.equal(
+ moment()
+ .add({ s: 30 })
+ .fromNow(),
+ 'em poucos segundos',
+ 'in seconds'
+ );
+ assert.equal(
+ moment()
+ .add({ d: 5 })
+ .fromNow(),
+ 'em 5 dias',
+ 'in 5 days'
+ );
+});
+
+test('calendar day', function() {
+ var a = moment()
+ .hours(12)
+ .minutes(0)
+ .seconds(0);
+
+ assert.equal(moment(a).calendar(), 'Hoje às 12:00', 'today at the same time');
+ assert.equal(
+ moment(a)
+ .add({ m: 25 })
+ .calendar(),
+ 'Hoje às 12:25',
+ 'Now plus 25 min'
+ );
+ assert.equal(
+ moment(a)
+ .add({ h: 1 })
+ .calendar(),
+ 'Hoje às 13:00',
+ 'Now plus 1 hour'
+ );
+ assert.equal(
+ moment(a)
+ .add({ d: 1 })
+ .calendar(),
+ 'Amanhã às 12:00',
+ 'tomorrow at the same time'
+ );
+ assert.equal(
+ moment(a)
+ .subtract({ h: 1 })
+ .calendar(),
+ 'Hoje às 11:00',
+ 'Now minus 1 hour'
+ );
+ assert.equal(
+ moment(a)
+ .subtract({ d: 1 })
+ .calendar(),
+ 'Ontem às 12:00',
+ 'yesterday at the same time'
+ );
+});
+
+test('calendar next week', function() {
+ var i, m;
+ for (i = 2; i < 7; i++) {
+ m = moment().add({ d: i });
+ assert.equal(
+ m.calendar(),
+ m.format('dddd [às] LT'),
+ 'Today + ' + i + ' days current time'
+ );
+ m.hours(0)
+ .minutes(0)
+ .seconds(0)
+ .milliseconds(0);
+ assert.equal(
+ m.calendar(),
+ m.format('dddd [às] LT'),
+ 'Today + ' + i + ' days beginning of day'
+ );
+ m.hours(23)
+ .minutes(59)
+ .seconds(59)
+ .milliseconds(999);
+ assert.equal(
+ m.calendar(),
+ m.format('dddd [às] LT'),
+ 'Today + ' + i + ' days end of day'
+ );
+ }
+});
+
+test('calendar last week', function() {
+ var i, m;
+ for (i = 2; i < 7; i++) {
+ m = moment().subtract({ d: i });
+ assert.equal(
+ m.calendar(),
+ m.format(
+ m.day() === 0 || m.day() === 6
+ ? '[Último] dddd [às] LT'
+ : '[Última] dddd [às] LT'
+ ),
+ 'Today - ' + i + ' days current time'
+ );
+ m.hours(0)
+ .minutes(0)
+ .seconds(0)
+ .milliseconds(0);
+ assert.equal(
+ m.calendar(),
+ m.format(
+ m.day() === 0 || m.day() === 6
+ ? '[Último] dddd [às] LT'
+ : '[Última] dddd [às] LT'
+ ),
+ 'Today - ' + i + ' days beginning of day'
+ );
+ m.hours(23)
+ .minutes(59)
+ .seconds(59)
+ .milliseconds(999);
+ assert.equal(
+ m.calendar(),
+ m.format(
+ m.day() === 0 || m.day() === 6
+ ? '[Último] dddd [às] LT'
+ : '[Última] dddd [às] LT'
+ ),
+ 'Today - ' + i + ' days end of day'
+ );
+ }
+});
+
+test('calendar all else', function() {
+ var weeksAgo = moment().subtract({ w: 1 }),
+ weeksFromNow = moment().add({ w: 1 });
+
+ assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago');
+ assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week');
+
+ weeksAgo = moment().subtract({ w: 2 });
+ weeksFromNow = moment().add({ w: 2 });
+
+ assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago');
+ assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks');
+});
+
+test('weeks year starting sunday format', function() {
+ assert.equal(
+ moment([2012, 0, 1]).format('w ww wo'),
+ '1 01 1º',
+ 'Jan 1 2012 should be week 1'
+ );
+ assert.equal(
+ moment([2012, 0, 7]).format('w ww wo'),
+ '1 01 1º',
+ 'Jan 7 2012 should be week 1'
+ );
+ assert.equal(
+ moment([2012, 0, 8]).format('w ww wo'),
+ '2 02 2º',
+ 'Jan 8 2012 should be week 2'
+ );
+ assert.equal(
+ moment([2012, 0, 14]).format('w ww wo'),
+ '2 02 2º',
+ 'Jan 14 2012 should be week 2'
+ );
+ assert.equal(
+ moment([2012, 0, 15]).format('w ww wo'),
+ '3 03 3º',
+ 'Jan 15 2012 should be week 3'
+ );
+});
+
+test('relative time threshold', function() {
+ var rts = moment(),
+ rtsDefault = moment.relativeTimeThreshold('ss');
+
+ moment.relativeTimeThreshold('ss', 3);
+
+ rts.subtract(3, 'seconds');
+ assert.equal(
+ rts.fromNow(),
+ 'há poucos segundos',
+ 'Below custom a few seconds to seconds threshold'
+ );
+ rts.subtract(1, 'seconds');
+ assert.equal(
+ rts.fromNow(),
+ 'há 4 segundos',
+ 'Above custom a few seconds to seconds threshold'
+ );
+
+ moment.relativeTimeThreshold('ss', rtsDefault);
+});
diff --git a/packages/utilities/psammead-locales/moment/ru.js b/packages/utilities/psammead-locales/moment/ru.js
new file mode 100644
index 0000000000..d3de5b78fc
--- /dev/null
+++ b/packages/utilities/psammead-locales/moment/ru.js
@@ -0,0 +1,10 @@
+var moment = require('moment');
+require('moment/locale/ru');
+
+moment.updateLocale('ru', {
+ longDateFormat: {
+ LL: 'D MMMM YYYY',
+ LLL: 'D MMMM YYYY, H:mm',
+ LLLL: 'dddd, D MMMM YYYY, H:mm',
+ },
+});
diff --git a/packages/utilities/psammead-locales/moment/ru.test.js b/packages/utilities/psammead-locales/moment/ru.test.js
new file mode 100644
index 0000000000..f5e71035f7
--- /dev/null
+++ b/packages/utilities/psammead-locales/moment/ru.test.js
@@ -0,0 +1,742 @@
+import moment from 'moment';
+import './ru';
+
+moment.locale('ru');
+
+// This asset overrides the gunit assertion done in the moment codebase.
+// Format and styling of this file has been keep consistent with the official moment tests.
+// An example of these tests can be seen at https://github.com/moment/moment/blob/develop/src/test/locale/en-gb.js
+const assert = { equal: (val1, val2) => expect(val1).toEqual(val2) };
+
+test('parse', function() {
+ var tests = 'январь янв._февраль февр._март март_апрель апр._май май_июнь июнь_июль июль_август авг._сентябрь сент._октябрь окт._ноябрь нояб._декабрь дек.'.split(
+ '_'
+ ),
+ i;
+ function equalTest(input, mmm, i) {
+ assert.equal(
+ moment(input, mmm).month(),
+ i,
+ input + ' should be month ' + (i + 1)
+ );
+ }
+ function equalTestStrict(input, mmm, monthIndex) {
+ assert.equal(
+ moment(input, mmm, true).month(),
+ monthIndex,
+ input + ' ' + mmm + ' should be strict month ' + (monthIndex + 1)
+ );
+ }
+ for (i = 0; i < 12; i++) {
+ tests[i] = tests[i].split(' ');
+ equalTest(tests[i][0], 'MMM', i);
+ equalTest(tests[i][1], 'MMM', i);
+ equalTest(tests[i][0], 'MMMM', i);
+ equalTest(tests[i][1], 'MMMM', i);
+ equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i);
+ equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i);
+ equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i);
+ equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i);
+
+ equalTestStrict(tests[i][1], 'MMM', i);
+ equalTestStrict(tests[i][0], 'MMMM', i);
+ equalTestStrict(tests[i][1].toLocaleLowerCase(), 'MMM', i);
+ equalTestStrict(tests[i][1].toLocaleUpperCase(), 'MMM', i);
+ equalTestStrict(tests[i][0].toLocaleLowerCase(), 'MMMM', i);
+ equalTestStrict(tests[i][0].toLocaleUpperCase(), 'MMMM', i);
+ }
+});
+
+test('parse exceptional case', function() {
+ assert.equal(
+ moment('11 Мая 1989', ['DD MMMM YYYY']).format('DD-MM-YYYY'),
+ '11-05-1989'
+ );
+});
+
+test('format', function() {
+ var a = [
+ [
+ 'dddd, Do MMMM YYYY, HH:mm:ss',
+ 'воскресенье, 14-го февраля 2010, 15:25:50',
+ ],
+ ['ddd, h A', 'вс, 3 дня'],
+ ['M Mo MM MMMM MMM', '2 2-й 02 февраль февр.'],
+ ['YYYY YY', '2010 10'],
+ ['D Do DD', '14 14-го 14'],
+ ['d do dddd ddd dd', '0 0-й воскресенье вс вс'],
+ ['DDD DDDo DDDD', '45 45-й 045'],
+ ['w wo ww', '6 6-я 06'],
+ ['h hh', '3 03'],
+ ['H HH', '15 15'],
+ ['m mm', '25 25'],
+ ['s ss', '50 50'],
+ ['a A', 'дня дня'],
+ ['DDDo [день года]', '45-й день года'],
+ ['LT', '15:25'],
+ ['LTS', '15:25:50'],
+ ['L', '14.02.2010'],
+ ['LL', '14 февраля 2010'],
+ ['LLL', '14 февраля 2010, 15:25'],
+ ['LLLL', 'воскресенье, 14 февраля 2010, 15:25'],
+ ['l', '14.2.2010'],
+ ['ll', '14 февр. 2010'],
+ ['lll', '14 февр. 2010, 15:25'],
+ ['llll', 'вс, 14 февр. 2010, 15:25'],
+ ],
+ b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)),
+ i;
+ for (i = 0; i < a.length; i++) {
+ assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]);
+ }
+});
+
+test('format meridiem', function() {
+ assert.equal(moment([2012, 11, 28, 0, 0]).format('A'), 'ночи', 'night');
+ assert.equal(moment([2012, 11, 28, 3, 59]).format('A'), 'ночи', 'night');
+ assert.equal(moment([2012, 11, 28, 4, 0]).format('A'), 'утра', 'morning');
+ assert.equal(moment([2012, 11, 28, 11, 59]).format('A'), 'утра', 'morning');
+ assert.equal(moment([2012, 11, 28, 12, 0]).format('A'), 'дня', 'afternoon');
+ assert.equal(moment([2012, 11, 28, 16, 59]).format('A'), 'дня', 'afternoon');
+ assert.equal(moment([2012, 11, 28, 17, 0]).format('A'), 'вечера', 'evening');
+ assert.equal(moment([2012, 11, 28, 23, 59]).format('A'), 'вечера', 'evening');
+});
+
+test('format ordinal', function() {
+ assert.equal(moment([2011, 0, 1]).format('DDDo'), '1-й', '1-й');
+ assert.equal(moment([2011, 0, 2]).format('DDDo'), '2-й', '2-й');
+ assert.equal(moment([2011, 0, 3]).format('DDDo'), '3-й', '3-й');
+ assert.equal(moment([2011, 0, 4]).format('DDDo'), '4-й', '4-й');
+ assert.equal(moment([2011, 0, 5]).format('DDDo'), '5-й', '5-й');
+ assert.equal(moment([2011, 0, 6]).format('DDDo'), '6-й', '6-й');
+ assert.equal(moment([2011, 0, 7]).format('DDDo'), '7-й', '7-й');
+ assert.equal(moment([2011, 0, 8]).format('DDDo'), '8-й', '8-й');
+ assert.equal(moment([2011, 0, 9]).format('DDDo'), '9-й', '9-й');
+ assert.equal(moment([2011, 0, 10]).format('DDDo'), '10-й', '10-й');
+
+ assert.equal(moment([2011, 0, 11]).format('DDDo'), '11-й', '11-й');
+ assert.equal(moment([2011, 0, 12]).format('DDDo'), '12-й', '12-й');
+ assert.equal(moment([2011, 0, 13]).format('DDDo'), '13-й', '13-й');
+ assert.equal(moment([2011, 0, 14]).format('DDDo'), '14-й', '14-й');
+ assert.equal(moment([2011, 0, 15]).format('DDDo'), '15-й', '15-й');
+ assert.equal(moment([2011, 0, 16]).format('DDDo'), '16-й', '16-й');
+ assert.equal(moment([2011, 0, 17]).format('DDDo'), '17-й', '17-й');
+ assert.equal(moment([2011, 0, 18]).format('DDDo'), '18-й', '18-й');
+ assert.equal(moment([2011, 0, 19]).format('DDDo'), '19-й', '19-й');
+ assert.equal(moment([2011, 0, 20]).format('DDDo'), '20-й', '20-й');
+
+ assert.equal(moment([2011, 0, 21]).format('DDDo'), '21-й', '21-й');
+ assert.equal(moment([2011, 0, 22]).format('DDDo'), '22-й', '22-й');
+ assert.equal(moment([2011, 0, 23]).format('DDDo'), '23-й', '23-й');
+ assert.equal(moment([2011, 0, 24]).format('DDDo'), '24-й', '24-й');
+ assert.equal(moment([2011, 0, 25]).format('DDDo'), '25-й', '25-й');
+ assert.equal(moment([2011, 0, 26]).format('DDDo'), '26-й', '26-й');
+ assert.equal(moment([2011, 0, 27]).format('DDDo'), '27-й', '27-й');
+ assert.equal(moment([2011, 0, 28]).format('DDDo'), '28-й', '28-й');
+ assert.equal(moment([2011, 0, 29]).format('DDDo'), '29-й', '29-й');
+ assert.equal(moment([2011, 0, 30]).format('DDDo'), '30-й', '30-й');
+
+ assert.equal(moment([2011, 0, 31]).format('DDDo'), '31-й', '31-й');
+});
+
+test('format month', function() {
+ var expected = 'январь янв._февраль февр._март март_апрель апр._май май_июнь июнь_июль июль_август авг._сентябрь сент._октябрь окт._ноябрь нояб._декабрь дек.'.split(
+ '_'
+ ),
+ i;
+ for (i = 0; i < expected.length; i++) {
+ assert.equal(
+ moment([2011, i, 1]).format('MMMM MMM'),
+ expected[i],
+ expected[i]
+ );
+ }
+});
+
+test('format month case', function() {
+ var months = {
+ nominative: 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split(
+ '_'
+ ),
+ accusative: 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split(
+ '_'
+ ),
+ },
+ i;
+ for (i = 0; i < 12; i++) {
+ assert.equal(
+ moment([2011, i, 1]).format('D MMMM'),
+ '1 ' + months.accusative[i],
+ '1 ' + months.accusative[i]
+ );
+ assert.equal(
+ moment([2011, i, 1]).format('MMMM'),
+ months.nominative[i],
+ '1 ' + months.nominative[i]
+ );
+ }
+});
+
+test('format month short case', function() {
+ var monthsShort = {
+ nominative: 'янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.'.split(
+ '_'
+ ),
+ accusative: 'янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.'.split(
+ '_'
+ ),
+ },
+ i;
+ for (i = 0; i < 12; i++) {
+ assert.equal(
+ moment([2011, i, 1]).format('D MMM'),
+ '1 ' + monthsShort.accusative[i],
+ '1 ' + monthsShort.accusative[i]
+ );
+ assert.equal(
+ moment([2011, i, 1]).format('MMM'),
+ monthsShort.nominative[i],
+ '1 ' + monthsShort.nominative[i]
+ );
+ }
+});
+
+test('format month case with escaped symbols', function() {
+ var months = {
+ nominative: 'январь_февраль_март_апрель_май_июнь_июль_август_сентябрь_октябрь_ноябрь_декабрь'.split(
+ '_'
+ ),
+ accusative: 'января_февраля_марта_апреля_мая_июня_июля_августа_сентября_октября_ноября_декабря'.split(
+ '_'
+ ),
+ },
+ i;
+ for (i = 0; i < 12; i++) {
+ assert.equal(
+ moment([2013, i, 1]).format('D[] MMMM'),
+ '1 ' + months.accusative[i],
+ '1 ' + months.accusative[i]
+ );
+ assert.equal(
+ moment([2013, i, 1]).format('[]D[] []MMMM[]'),
+ '1 ' + months.accusative[i] + '',
+ '1 ' + months.accusative[i] + ''
+ );
+ assert.equal(
+ moment([2013, i, 1]).format('D[-й день] MMMM'),
+ '1-й день ' + months.accusative[i],
+ '1-й день ' + months.accusative[i]
+ );
+ assert.equal(
+ moment([2013, i, 1]).format('D, MMMM'),
+ '1, ' + months.nominative[i],
+ '1, ' + months.nominative[i]
+ );
+ }
+});
+
+test('format month short case with escaped symbols', function() {
+ var monthsShort = {
+ nominative: 'янв._февр._март_апр._май_июнь_июль_авг._сент._окт._нояб._дек.'.split(
+ '_'
+ ),
+ accusative: 'янв._февр._мар._апр._мая_июня_июля_авг._сент._окт._нояб._дек.'.split(
+ '_'
+ ),
+ },
+ i;
+ for (i = 0; i < 12; i++) {
+ assert.equal(
+ moment([2013, i, 1]).format('D[] MMM'),
+ '1 ' + monthsShort.accusative[i],
+ '1 ' + monthsShort.accusative[i]
+ );
+ assert.equal(
+ moment([2013, i, 1]).format('[]D[] []MMM[]'),
+ '1 ' + monthsShort.accusative[i] + '',
+ '1 ' + monthsShort.accusative[i] + ''
+ );
+ assert.equal(
+ moment([2013, i, 1]).format('D[-й день] MMM'),
+ '1-й день ' + monthsShort.accusative[i],
+ '1-й день ' + monthsShort.accusative[i]
+ );
+ assert.equal(
+ moment([2013, i, 1]).format('D, MMM'),
+ '1, ' + monthsShort.nominative[i],
+ '1, ' + monthsShort.nominative[i]
+ );
+ }
+});
+
+test('format week', function() {
+ var expected = 'воскресенье вс вс_понедельник пн пн_вторник вт вт_среда ср ср_четверг чт чт_пятница пт пт_суббота сб сб'.split(
+ '_'
+ ),
+ i;
+ for (i = 0; i < expected.length; i++) {
+ assert.equal(
+ moment([2011, 0, 2 + i]).format('dddd ddd dd'),
+ expected[i],
+ expected[i]
+ );
+ }
+});
+
+test('from', function() {
+ var start = moment([2007, 1, 28]);
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 44 }), true),
+ 'несколько секунд',
+ '44 seconds = seconds'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 45 }), true),
+ 'минута',
+ '45 seconds = a minute'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 89 }), true),
+ 'минута',
+ '89 seconds = a minute'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 90 }), true),
+ '2 минуты',
+ '90 seconds = 2 minutes'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 31 }), true),
+ '31 минута',
+ '31 minutes = 31 minutes'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 44 }), true),
+ '44 минуты',
+ '44 minutes = 44 minutes'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 45 }), true),
+ 'час',
+ '45 minutes = an hour'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 89 }), true),
+ 'час',
+ '89 minutes = an hour'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 90 }), true),
+ '2 часа',
+ '90 minutes = 2 hours'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 5 }), true),
+ '5 часов',
+ '5 hours = 5 hours'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 21 }), true),
+ '21 час',
+ '21 hours = 21 hours'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 22 }), true),
+ 'день',
+ '22 hours = a day'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 35 }), true),
+ 'день',
+ '35 hours = a day'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 36 }), true),
+ '2 дня',
+ '36 hours = 2 days'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 1 }), true),
+ 'день',
+ '1 day = a day'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 5 }), true),
+ '5 дней',
+ '5 days = 5 days'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 11 }), true),
+ '11 дней',
+ '11 days = 11 days'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 21 }), true),
+ '21 день',
+ '21 days = 21 days'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 25 }), true),
+ '25 дней',
+ '25 days = 25 days'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 26 }), true),
+ 'месяц',
+ '26 days = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 30 }), true),
+ 'месяц',
+ '30 days = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 43 }), true),
+ 'месяц',
+ '43 days = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 46 }), true),
+ '2 месяца',
+ '46 days = 2 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 74 }), true),
+ '2 месяца',
+ '75 days = 2 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 76 }), true),
+ '3 месяца',
+ '76 days = 3 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ M: 1 }), true),
+ 'месяц',
+ '1 month = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ M: 5 }), true),
+ '5 месяцев',
+ '5 months = 5 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 345 }), true),
+ 'год',
+ '345 days = a year'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 548 }), true),
+ '2 года',
+ '548 days = 2 years'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ y: 1 }), true),
+ 'год',
+ '1 year = a year'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ y: 5 }), true),
+ '5 лет',
+ '5 years = 5 years'
+ );
+});
+
+test('suffix', function() {
+ assert.equal(moment(30000).from(0), 'через несколько секунд', 'prefix');
+ assert.equal(moment(0).from(30000), 'несколько секунд назад', 'suffix');
+});
+
+test('fromNow', function() {
+ assert.equal(
+ moment()
+ .add({ s: 30 })
+ .fromNow(),
+ 'через несколько секунд',
+ 'in seconds'
+ );
+ assert.equal(
+ moment()
+ .add({ d: 5 })
+ .fromNow(),
+ 'через 5 дней',
+ 'in 5 days'
+ );
+ assert.equal(
+ moment()
+ .add({ m: 31 })
+ .fromNow(),
+ 'через 31 минуту',
+ 'in 31 minutes = in 31 minutes'
+ );
+ assert.equal(
+ moment()
+ .subtract({ m: 31 })
+ .fromNow(),
+ '31 минуту назад',
+ '31 minutes ago = 31 minutes ago'
+ );
+});
+
+test('calendar day', function() {
+ var a = moment()
+ .hours(12)
+ .minutes(0)
+ .seconds(0);
+
+ assert.equal(
+ moment(a).calendar(),
+ 'Сегодня, в 12:00',
+ 'today at the same time'
+ );
+ assert.equal(
+ moment(a)
+ .add({ m: 25 })
+ .calendar(),
+ 'Сегодня, в 12:25',
+ 'Now plus 25 min'
+ );
+ assert.equal(
+ moment(a)
+ .add({ h: 1 })
+ .calendar(),
+ 'Сегодня, в 13:00',
+ 'Now plus 1 hour'
+ );
+ assert.equal(
+ moment(a)
+ .add({ d: 1 })
+ .calendar(),
+ 'Завтра, в 12:00',
+ 'tomorrow at the same time'
+ );
+ assert.equal(
+ moment(a)
+ .subtract({ h: 1 })
+ .calendar(),
+ 'Сегодня, в 11:00',
+ 'Now minus 1 hour'
+ );
+ assert.equal(
+ moment(a)
+ .subtract({ h: 4 })
+ .calendar(),
+ 'Сегодня, в 8:00',
+ 'Now minus 4 hours'
+ );
+ assert.equal(
+ moment(a)
+ .subtract({ d: 1 })
+ .calendar(),
+ 'Вчера, в 12:00',
+ 'yesterday at the same time'
+ );
+});
+
+test('calendar next week', function() {
+ var i, m, now;
+
+ function makeFormatNext(d) {
+ switch (d.day()) {
+ case 0:
+ return '[В следующее] dddd, [в] LT';
+ case 1:
+ case 2:
+ case 4:
+ return '[В следующий] dddd, [в] LT';
+ case 3:
+ case 5:
+ case 6:
+ return '[В следующую] dddd, [в] LT';
+ }
+ }
+
+ function makeFormatThis(d) {
+ if (d.day() === 2) {
+ return '[Во] dddd, [в] LT';
+ } else {
+ return '[В] dddd, [в] LT';
+ }
+ }
+
+ now = moment().startOf('week');
+ for (i = 2; i < 7; i++) {
+ m = moment(now).add({ d: i });
+ assert.equal(
+ m.calendar(now),
+ m.format(makeFormatThis(m)),
+ 'Today + ' + i + ' days current time'
+ );
+ m.hours(0)
+ .minutes(0)
+ .seconds(0)
+ .milliseconds(0);
+ assert.equal(
+ m.calendar(now),
+ m.format(makeFormatThis(m)),
+ 'Today + ' + i + ' days beginning of day'
+ );
+ m.hours(23)
+ .minutes(59)
+ .seconds(59)
+ .milliseconds(999);
+ assert.equal(
+ m.calendar(now),
+ m.format(makeFormatThis(m)),
+ 'Today + ' + i + ' days end of day'
+ );
+ }
+
+ now = moment().endOf('week');
+ for (i = 2; i < 7; i++) {
+ m = moment(now).add({ d: i });
+ assert.equal(
+ m.calendar(now),
+ m.format(makeFormatNext(m)),
+ 'Today + ' + i + ' days current time'
+ );
+ m.hours(0)
+ .minutes(0)
+ .seconds(0)
+ .milliseconds(0);
+ assert.equal(
+ m.calendar(now),
+ m.format(makeFormatNext(m)),
+ 'Today + ' + i + ' days beginning of day'
+ );
+ m.hours(23)
+ .minutes(59)
+ .seconds(59)
+ .milliseconds(999);
+ assert.equal(
+ m.calendar(now),
+ m.format(makeFormatNext(m)),
+ 'Today + ' + i + ' days end of day'
+ );
+ }
+});
+
+test('calendar last week', function() {
+ var i, m, now;
+
+ function makeFormatLast(d) {
+ switch (d.day()) {
+ case 0:
+ return '[В прошлое] dddd, [в] LT';
+ case 1:
+ case 2:
+ case 4:
+ return '[В прошлый] dddd, [в] LT';
+ case 3:
+ case 5:
+ case 6:
+ return '[В прошлую] dddd, [в] LT';
+ }
+ }
+
+ function makeFormatThis(d) {
+ if (d.day() === 2) {
+ return '[Во] dddd, [в] LT';
+ } else {
+ return '[В] dddd, [в] LT';
+ }
+ }
+
+ now = moment().startOf('week');
+ for (i = 2; i < 7; i++) {
+ m = moment(now).subtract({ d: i });
+ assert.equal(
+ m.calendar(now),
+ m.format(makeFormatLast(m)),
+ 'Today - ' + i + ' days current time'
+ );
+ m.hours(0)
+ .minutes(0)
+ .seconds(0)
+ .milliseconds(0);
+ assert.equal(
+ m.calendar(now),
+ m.format(makeFormatLast(m)),
+ 'Today - ' + i + ' days beginning of day'
+ );
+ m.hours(23)
+ .minutes(59)
+ .seconds(59)
+ .milliseconds(999);
+ assert.equal(
+ m.calendar(now),
+ m.format(makeFormatLast(m)),
+ 'Today - ' + i + ' days end of day'
+ );
+ }
+
+ now = moment().endOf('week');
+ for (i = 2; i < 7; i++) {
+ m = moment(now).subtract({ d: i });
+ assert.equal(
+ m.calendar(now),
+ m.format(makeFormatThis(m)),
+ 'Today - ' + i + ' days current time'
+ );
+ m.hours(0)
+ .minutes(0)
+ .seconds(0)
+ .milliseconds(0);
+ assert.equal(
+ m.calendar(now),
+ m.format(makeFormatThis(m)),
+ 'Today - ' + i + ' days beginning of day'
+ );
+ m.hours(23)
+ .minutes(59)
+ .seconds(59)
+ .milliseconds(999);
+ assert.equal(
+ m.calendar(now),
+ m.format(makeFormatThis(m)),
+ 'Today - ' + i + ' days end of day'
+ );
+ }
+});
+
+test('calendar all else', function() {
+ var weeksAgo = moment().subtract({ w: 1 }),
+ weeksFromNow = moment().add({ w: 1 });
+
+ assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago');
+ assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week');
+
+ weeksAgo = moment().subtract({ w: 2 });
+ weeksFromNow = moment().add({ w: 2 });
+
+ assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago');
+ assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks');
+});
+
+test('weeks year starting monday formatted', function() {
+ assert.equal(
+ moment([2011, 11, 26]).format('w ww wo'),
+ '52 52 52-я',
+ 'Dec 26 2011 should be week 52'
+ );
+ assert.equal(
+ moment([2012, 0, 1]).format('w ww wo'),
+ '52 52 52-я',
+ 'Jan 1 2012 should be week 52'
+ );
+ assert.equal(
+ moment([2012, 0, 2]).format('w ww wo'),
+ '1 01 1-я',
+ 'Jan 2 2012 should be week 1'
+ );
+ assert.equal(
+ moment([2012, 0, 8]).format('w ww wo'),
+ '1 01 1-я',
+ 'Jan 8 2012 should be week 1'
+ );
+ assert.equal(
+ moment([2012, 0, 9]).format('w ww wo'),
+ '2 02 2-я',
+ 'Jan 9 2012 should be week 2'
+ );
+});
diff --git a/packages/utilities/psammead-locales/moment/sr-cyrl.js b/packages/utilities/psammead-locales/moment/sr-cyrl.js
new file mode 100644
index 0000000000..5d74104b9b
--- /dev/null
+++ b/packages/utilities/psammead-locales/moment/sr-cyrl.js
@@ -0,0 +1,10 @@
+var moment = require('moment');
+require('moment/locale/sr-cyrl');
+
+moment.updateLocale('sr-cyrl', {
+ longDateFormat: {
+ LL: 'D MMMM YYYY',
+ LLL: 'D MMMM YYYY H:mm',
+ LLLL: 'dddd, D MMMM YYYY H:mm',
+ },
+});
diff --git a/packages/utilities/psammead-locales/moment/sr-cyrl.test.js b/packages/utilities/psammead-locales/moment/sr-cyrl.test.js
new file mode 100644
index 0000000000..64acc7bc54
--- /dev/null
+++ b/packages/utilities/psammead-locales/moment/sr-cyrl.test.js
@@ -0,0 +1,484 @@
+import moment from 'moment';
+import './sr-cyrl';
+
+moment.locale('sr-cyrl');
+
+// This asset overrides the gunit assertion done in the moment codebase.
+// Format and styling of this file has been keep consistent with the official moment tests.
+// An example of these tests can be seen at https://github.com/moment/moment/blob/develop/src/test/locale/en-gb.js
+const assert = { equal: (val1, val2) => expect(val1).toEqual(val2) };
+
+test('parse', function() {
+ var tests = 'јануар јан._фебруар феб._март мар._април апр._мај мај_јун јун_јул јул_август авг._септембар сеп._октобар окт._новембар нов._децембар дец.'.split(
+ '_'
+ ),
+ i;
+ function equalTest(input, mmm, i) {
+ assert.equal(
+ moment(input, mmm).month(),
+ i,
+ input + ' should be month ' + (i + 1)
+ );
+ }
+ for (i = 0; i < 12; i++) {
+ tests[i] = tests[i].split(' ');
+ equalTest(tests[i][0], 'MMM', i);
+ equalTest(tests[i][1], 'MMM', i);
+ equalTest(tests[i][0], 'MMMM', i);
+ equalTest(tests[i][1], 'MMMM', i);
+ equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i);
+ equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i);
+ equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i);
+ equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i);
+ }
+});
+
+test('format', function() {
+ var a = [
+ ['dddd, Do MMMM YYYY, h:mm:ss a', 'недеља, 14. фебруар 2010, 3:25:50 pm'],
+ ['ddd, hA', 'нед., 3PM'],
+ ['M Mo MM MMMM MMM', '2 2. 02 фебруар феб.'],
+ ['YYYY YY', '2010 10'],
+ ['D Do DD', '14 14. 14'],
+ ['d do dddd ddd dd', '0 0. недеља нед. не'],
+ ['DDD DDDo DDDD', '45 45. 045'],
+ ['w wo ww', '7 7. 07'],
+ ['h hh', '3 03'],
+ ['H HH', '15 15'],
+ ['m mm', '25 25'],
+ ['s ss', '50 50'],
+ ['a A', 'pm PM'],
+ ['[the] DDDo [day of the year]', 'the 45. day of the year'],
+ ['LTS', '15:25:50'],
+ ['L', '14.02.2010'],
+ ['LL', '14 фебруар 2010'],
+ ['LLL', '14 фебруар 2010 15:25'],
+ ['LLLL', 'недеља, 14 фебруар 2010 15:25'],
+ ['l', '14.2.2010'],
+ ['ll', '14 феб. 2010'],
+ ['lll', '14 феб. 2010 15:25'],
+ ['llll', 'нед., 14 феб. 2010 15:25'],
+ ],
+ b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)),
+ i;
+ for (i = 0; i < a.length; i++) {
+ assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]);
+ }
+});
+
+test('format ordinal', function() {
+ assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.');
+ assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.');
+ assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.');
+ assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.');
+ assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.');
+ assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.');
+ assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.');
+ assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.');
+ assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.');
+ assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.');
+
+ assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.');
+ assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.');
+ assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.');
+ assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.');
+ assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.');
+ assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.');
+ assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.');
+ assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.');
+ assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.');
+ assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.');
+
+ assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.');
+ assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.');
+ assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.');
+ assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.');
+ assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.');
+ assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.');
+ assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.');
+ assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.');
+ assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.');
+ assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.');
+
+ assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.');
+});
+
+test('format month', function() {
+ var expected = 'јануар јан._фебруар феб._март мар._април апр._мај мај_јун јун_јул јул_август авг._септембар сеп._октобар окт._новембар нов._децембар дец.'.split(
+ '_'
+ ),
+ i;
+ for (i = 0; i < expected.length; i++) {
+ assert.equal(
+ moment([2011, i, 1]).format('MMMM MMM'),
+ expected[i],
+ expected[i]
+ );
+ }
+});
+
+test('format week', function() {
+ var expected = 'недеља нед. не_понедељак пон. по_уторак уто. ут_среда сре. ср_четвртак чет. че_петак пет. пе_субота суб. су'.split(
+ '_'
+ ),
+ i;
+ for (i = 0; i < expected.length; i++) {
+ assert.equal(
+ moment([2011, 0, 2 + i]).format('dddd ddd dd'),
+ expected[i],
+ expected[i]
+ );
+ }
+});
+
+test('from', function() {
+ var start = moment([2007, 1, 28]);
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 44 }), true),
+ 'неколико секунди',
+ '44 seconds = a few seconds'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 45 }), true),
+ 'један минут',
+ '45 seconds = a minute'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 89 }), true),
+ 'један минут',
+ '89 seconds = a minute'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 90 }), true),
+ '2 минуте',
+ '90 seconds = 2 minutes'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 44 }), true),
+ '44 минута',
+ '44 minutes = 44 minutes'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 45 }), true),
+ 'један сат',
+ '45 minutes = an hour'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 89 }), true),
+ 'један сат',
+ '89 minutes = an hour'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 90 }), true),
+ '2 сата',
+ '90 minutes = 2 hours'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 5 }), true),
+ '5 сати',
+ '5 hours = 5 hours'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 21 }), true),
+ '21 сати',
+ '21 hours = 21 hours'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 22 }), true),
+ 'дан',
+ '22 hours = a day'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 35 }), true),
+ 'дан',
+ '35 hours = a day'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 36 }), true),
+ '2 дана',
+ '36 hours = 2 days'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 1 }), true),
+ 'дан',
+ '1 day = a day'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 5 }), true),
+ '5 дана',
+ '5 days = 5 days'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 25 }), true),
+ '25 дана',
+ '25 days = 25 days'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 26 }), true),
+ 'месец',
+ '26 days = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 30 }), true),
+ 'месец',
+ '30 days = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 43 }), true),
+ 'месец',
+ '43 days = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 46 }), true),
+ '2 месеца',
+ '46 days = 2 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 74 }), true),
+ '2 месеца',
+ '75 days = 2 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 76 }), true),
+ '3 месеца',
+ '76 days = 3 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ M: 1 }), true),
+ 'месец',
+ '1 month = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ M: 5 }), true),
+ '5 месеци',
+ '5 months = 5 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 345 }), true),
+ 'годину',
+ '345 days = a year'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 548 }), true),
+ '2 године',
+ '548 days = 2 years'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ y: 1 }), true),
+ 'годину',
+ '1 year = a year'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ y: 5 }), true),
+ '5 година',
+ '5 years = 5 years'
+ );
+});
+
+test('suffix', function() {
+ assert.equal(moment(30000).from(0), 'за неколико секунди', 'prefix');
+ assert.equal(moment(0).from(30000), 'пре неколико секунди', 'prefix');
+});
+
+test('now from now', function() {
+ assert.equal(
+ moment().fromNow(),
+ 'пре неколико секунди',
+ 'now from now should display as in the past'
+ );
+});
+
+test('fromNow', function() {
+ assert.equal(
+ moment()
+ .add({ s: 30 })
+ .fromNow(),
+ 'за неколико секунди',
+ 'in a few seconds'
+ );
+ assert.equal(
+ moment()
+ .add({ d: 5 })
+ .fromNow(),
+ 'за 5 дана',
+ 'in 5 days'
+ );
+});
+
+test('calendar day', function() {
+ var a = moment()
+ .hours(12)
+ .minutes(0)
+ .seconds(0);
+
+ assert.equal(moment(a).calendar(), 'данас у 12:00', 'today at the same time');
+ assert.equal(
+ moment(a)
+ .add({ m: 25 })
+ .calendar(),
+ 'данас у 12:25',
+ 'Now plus 25 min'
+ );
+ assert.equal(
+ moment(a)
+ .add({ h: 1 })
+ .calendar(),
+ 'данас у 13:00',
+ 'Now plus 1 hour'
+ );
+ assert.equal(
+ moment(a)
+ .add({ d: 1 })
+ .calendar(),
+ 'сутра у 12:00',
+ 'tomorrow at the same time'
+ );
+ assert.equal(
+ moment(a)
+ .subtract({ h: 1 })
+ .calendar(),
+ 'данас у 11:00',
+ 'Now minus 1 hour'
+ );
+ assert.equal(
+ moment(a)
+ .subtract({ d: 1 })
+ .calendar(),
+ 'јуче у 12:00',
+ 'yesterday at the same time'
+ );
+});
+
+test('calendar next week', function() {
+ var i, m;
+
+ function makeFormat(d) {
+ switch (d.day()) {
+ case 0:
+ return '[у] [недељу] [у] LT';
+ case 3:
+ return '[у] [среду] [у] LT';
+ case 6:
+ return '[у] [суботу] [у] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[у] dddd [у] LT';
+ }
+ }
+
+ for (i = 2; i < 7; i++) {
+ m = moment().add({ d: i });
+ assert.equal(
+ m.calendar(),
+ m.format(makeFormat(m)),
+ 'Today + ' + i + ' days current time'
+ );
+ m.hours(0)
+ .minutes(0)
+ .seconds(0)
+ .milliseconds(0);
+ assert.equal(
+ m.calendar(),
+ m.format(makeFormat(m)),
+ 'Today + ' + i + ' days beginning of day'
+ );
+ m.hours(23)
+ .minutes(59)
+ .seconds(59)
+ .milliseconds(999);
+ assert.equal(
+ m.calendar(),
+ m.format(makeFormat(m)),
+ 'Today + ' + i + ' days end of day'
+ );
+ }
+});
+
+test('calendar last week', function() {
+ var i, m;
+
+ function makeFormat(d) {
+ var lastWeekDay = [
+ '[прошле] [недеље] [у] LT',
+ '[прошлог] [понедељка] [у] LT',
+ '[прошлог] [уторка] [у] LT',
+ '[прошле] [среде] [у] LT',
+ '[прошлог] [четвртка] [у] LT',
+ '[прошлог] [петка] [у] LT',
+ '[прошле] [суботе] [у] LT',
+ ];
+
+ return lastWeekDay[d.day()];
+ }
+
+ for (i = 2; i < 7; i++) {
+ m = moment().subtract({ d: i });
+ assert.equal(
+ m.calendar(),
+ m.format(makeFormat(m)),
+ 'Today - ' + i + ' days current time'
+ );
+ m.hours(0)
+ .minutes(0)
+ .seconds(0)
+ .milliseconds(0);
+ assert.equal(
+ m.calendar(),
+ m.format(makeFormat(m)),
+ 'Today - ' + i + ' days beginning of day'
+ );
+ m.hours(23)
+ .minutes(59)
+ .seconds(59)
+ .milliseconds(999);
+ assert.equal(
+ m.calendar(),
+ m.format(makeFormat(m)),
+ 'Today - ' + i + ' days end of day'
+ );
+ }
+});
+
+test('calendar all else', function() {
+ var weeksAgo = moment().subtract({ w: 1 }),
+ weeksFromNow = moment().add({ w: 1 });
+
+ assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago');
+ assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week');
+
+ weeksAgo = moment().subtract({ w: 2 });
+ weeksFromNow = moment().add({ w: 2 });
+
+ assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago');
+ assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks');
+});
+
+test('weeks year starting sunday formatted', function() {
+ assert.equal(
+ moment([2011, 11, 26]).format('w ww wo'),
+ '1 01 1.',
+ 'Dec 26 2011 should be week 1'
+ );
+ assert.equal(
+ moment([2012, 0, 1]).format('w ww wo'),
+ '1 01 1.',
+ 'Jan 1 2012 should be week 1'
+ );
+ assert.equal(
+ moment([2012, 0, 2]).format('w ww wo'),
+ '2 02 2.',
+ 'Jan 2 2012 should be week 2'
+ );
+ assert.equal(
+ moment([2012, 0, 8]).format('w ww wo'),
+ '2 02 2.',
+ 'Jan 8 2012 should be week 2'
+ );
+ assert.equal(
+ moment([2012, 0, 9]).format('w ww wo'),
+ '3 03 3.',
+ 'Jan 9 2012 should be week 3'
+ );
+});
diff --git a/packages/utilities/psammead-locales/moment/sr.js b/packages/utilities/psammead-locales/moment/sr.js
new file mode 100644
index 0000000000..20fe519bf6
--- /dev/null
+++ b/packages/utilities/psammead-locales/moment/sr.js
@@ -0,0 +1,10 @@
+var moment = require('moment');
+require('moment/locale/sr');
+
+moment.updateLocale('sr', {
+ longDateFormat: {
+ LL: 'D MMMM YYYY',
+ LLL: 'D MMMM YYYY H:mm',
+ LLLL: 'dddd, D MMMM YYYY H:mm',
+ },
+});
diff --git a/packages/utilities/psammead-locales/moment/sr.test.js b/packages/utilities/psammead-locales/moment/sr.test.js
new file mode 100644
index 0000000000..63c52e4526
--- /dev/null
+++ b/packages/utilities/psammead-locales/moment/sr.test.js
@@ -0,0 +1,487 @@
+import moment from 'moment';
+import './sr';
+
+moment.locale('sr');
+
+// This asset overrides the gunit assertion done in the moment codebase.
+// Format and styling of this file has been keep consistent with the official moment tests.
+// An example of these tests can be seen at https://github.com/moment/moment/blob/develop/src/test/locale/en-gb.js
+const assert = { equal: (val1, val2) => expect(val1).toEqual(val2) };
+
+test('parse', function() {
+ var tests = 'januar jan._februar feb._mart mar._april apr._maj maj_jun jun_jul jul_avgust avg._septembar sep._oktobar okt._novembar nov._decembar dec.'.split(
+ '_'
+ ),
+ i;
+ function equalTest(input, mmm, i) {
+ assert.equal(
+ moment(input, mmm).month(),
+ i,
+ input + ' should be month ' + (i + 1)
+ );
+ }
+ for (i = 0; i < 12; i++) {
+ tests[i] = tests[i].split(' ');
+ equalTest(tests[i][0], 'MMM', i);
+ equalTest(tests[i][1], 'MMM', i);
+ equalTest(tests[i][0], 'MMMM', i);
+ equalTest(tests[i][1], 'MMMM', i);
+ equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i);
+ equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i);
+ equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i);
+ equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i);
+ }
+});
+
+test('format', function() {
+ var a = [
+ [
+ 'dddd, Do MMMM YYYY, h:mm:ss a',
+ 'nedelja, 14. februar 2010, 3:25:50 pm',
+ ],
+ ['ddd, hA', 'ned., 3PM'],
+ ['M Mo MM MMMM MMM', '2 2. 02 februar feb.'],
+ ['YYYY YY', '2010 10'],
+ ['D Do DD', '14 14. 14'],
+ ['d do dddd ddd dd', '0 0. nedelja ned. ne'],
+ ['DDD DDDo DDDD', '45 45. 045'],
+ ['w wo ww', '7 7. 07'],
+ ['h hh', '3 03'],
+ ['H HH', '15 15'],
+ ['m mm', '25 25'],
+ ['s ss', '50 50'],
+ ['a A', 'pm PM'],
+ ['[the] DDDo [day of the year]', 'the 45. day of the year'],
+ ['LTS', '15:25:50'],
+ ['L', '14.02.2010'],
+ ['LL', '14 februar 2010'],
+ ['LLL', '14 februar 2010 15:25'],
+ ['LLLL', 'nedelja, 14 februar 2010 15:25'],
+ ['l', '14.2.2010'],
+ ['ll', '14 feb. 2010'],
+ ['lll', '14 feb. 2010 15:25'],
+ ['llll', 'ned., 14 feb. 2010 15:25'],
+ ],
+ b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)),
+ i;
+ for (i = 0; i < a.length; i++) {
+ assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]);
+ }
+});
+
+test('format ordinal', function() {
+ assert.equal(moment([2011, 0, 1]).format('DDDo'), '1.', '1.');
+ assert.equal(moment([2011, 0, 2]).format('DDDo'), '2.', '2.');
+ assert.equal(moment([2011, 0, 3]).format('DDDo'), '3.', '3.');
+ assert.equal(moment([2011, 0, 4]).format('DDDo'), '4.', '4.');
+ assert.equal(moment([2011, 0, 5]).format('DDDo'), '5.', '5.');
+ assert.equal(moment([2011, 0, 6]).format('DDDo'), '6.', '6.');
+ assert.equal(moment([2011, 0, 7]).format('DDDo'), '7.', '7.');
+ assert.equal(moment([2011, 0, 8]).format('DDDo'), '8.', '8.');
+ assert.equal(moment([2011, 0, 9]).format('DDDo'), '9.', '9.');
+ assert.equal(moment([2011, 0, 10]).format('DDDo'), '10.', '10.');
+
+ assert.equal(moment([2011, 0, 11]).format('DDDo'), '11.', '11.');
+ assert.equal(moment([2011, 0, 12]).format('DDDo'), '12.', '12.');
+ assert.equal(moment([2011, 0, 13]).format('DDDo'), '13.', '13.');
+ assert.equal(moment([2011, 0, 14]).format('DDDo'), '14.', '14.');
+ assert.equal(moment([2011, 0, 15]).format('DDDo'), '15.', '15.');
+ assert.equal(moment([2011, 0, 16]).format('DDDo'), '16.', '16.');
+ assert.equal(moment([2011, 0, 17]).format('DDDo'), '17.', '17.');
+ assert.equal(moment([2011, 0, 18]).format('DDDo'), '18.', '18.');
+ assert.equal(moment([2011, 0, 19]).format('DDDo'), '19.', '19.');
+ assert.equal(moment([2011, 0, 20]).format('DDDo'), '20.', '20.');
+
+ assert.equal(moment([2011, 0, 21]).format('DDDo'), '21.', '21.');
+ assert.equal(moment([2011, 0, 22]).format('DDDo'), '22.', '22.');
+ assert.equal(moment([2011, 0, 23]).format('DDDo'), '23.', '23.');
+ assert.equal(moment([2011, 0, 24]).format('DDDo'), '24.', '24.');
+ assert.equal(moment([2011, 0, 25]).format('DDDo'), '25.', '25.');
+ assert.equal(moment([2011, 0, 26]).format('DDDo'), '26.', '26.');
+ assert.equal(moment([2011, 0, 27]).format('DDDo'), '27.', '27.');
+ assert.equal(moment([2011, 0, 28]).format('DDDo'), '28.', '28.');
+ assert.equal(moment([2011, 0, 29]).format('DDDo'), '29.', '29.');
+ assert.equal(moment([2011, 0, 30]).format('DDDo'), '30.', '30.');
+
+ assert.equal(moment([2011, 0, 31]).format('DDDo'), '31.', '31.');
+});
+
+test('format month', function() {
+ var expected = 'januar jan._februar feb._mart mar._april apr._maj maj_jun jun_jul jul_avgust avg._septembar sep._oktobar okt._novembar nov._decembar dec.'.split(
+ '_'
+ ),
+ i;
+ for (i = 0; i < expected.length; i++) {
+ assert.equal(
+ moment([2011, i, 1]).format('MMMM MMM'),
+ expected[i],
+ expected[i]
+ );
+ }
+});
+
+test('format week', function() {
+ var expected = 'nedelja ned. ne_ponedeljak pon. po_utorak uto. ut_sreda sre. sr_četvrtak čet. če_petak pet. pe_subota sub. su'.split(
+ '_'
+ ),
+ i;
+ for (i = 0; i < expected.length; i++) {
+ assert.equal(
+ moment([2011, 0, 2 + i]).format('dddd ddd dd'),
+ expected[i],
+ expected[i]
+ );
+ }
+});
+
+test('from', function() {
+ var start = moment([2007, 1, 28]);
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 44 }), true),
+ 'nekoliko sekundi',
+ '44 seconds = a few seconds'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 45 }), true),
+ 'jedan minut',
+ '45 seconds = a minute'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 89 }), true),
+ 'jedan minut',
+ '89 seconds = a minute'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 90 }), true),
+ '2 minute',
+ '90 seconds = 2 minutes'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 44 }), true),
+ '44 minuta',
+ '44 minutes = 44 minutes'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 45 }), true),
+ 'jedan sat',
+ '45 minutes = an hour'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 89 }), true),
+ 'jedan sat',
+ '89 minutes = an hour'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 90 }), true),
+ '2 sata',
+ '90 minutes = 2 hours'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 5 }), true),
+ '5 sati',
+ '5 hours = 5 hours'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 21 }), true),
+ '21 sati',
+ '21 hours = 21 hours'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 22 }), true),
+ 'dan',
+ '22 hours = a day'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 35 }), true),
+ 'dan',
+ '35 hours = a day'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 36 }), true),
+ '2 dana',
+ '36 hours = 2 days'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 1 }), true),
+ 'dan',
+ '1 day = a day'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 5 }), true),
+ '5 dana',
+ '5 days = 5 days'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 25 }), true),
+ '25 dana',
+ '25 days = 25 days'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 26 }), true),
+ 'mesec',
+ '26 days = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 30 }), true),
+ 'mesec',
+ '30 days = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 43 }), true),
+ 'mesec',
+ '43 days = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 46 }), true),
+ '2 meseca',
+ '46 days = 2 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 74 }), true),
+ '2 meseca',
+ '75 days = 2 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 76 }), true),
+ '3 meseca',
+ '76 days = 3 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ M: 1 }), true),
+ 'mesec',
+ '1 month = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ M: 5 }), true),
+ '5 meseci',
+ '5 months = 5 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 345 }), true),
+ 'godinu',
+ '345 days = a year'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 548 }), true),
+ '2 godine',
+ '548 days = 2 years'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ y: 1 }), true),
+ 'godinu',
+ '1 year = a year'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ y: 5 }), true),
+ '5 godina',
+ '5 years = 5 years'
+ );
+});
+
+test('suffix', function() {
+ assert.equal(moment(30000).from(0), 'za nekoliko sekundi', 'prefix');
+ assert.equal(moment(0).from(30000), 'pre nekoliko sekundi', 'prefix');
+});
+
+test('now from now', function() {
+ assert.equal(
+ moment().fromNow(),
+ 'pre nekoliko sekundi',
+ 'now from now should display as in the past'
+ );
+});
+
+test('fromNow', function() {
+ assert.equal(
+ moment()
+ .add({ s: 30 })
+ .fromNow(),
+ 'za nekoliko sekundi',
+ 'in a few seconds'
+ );
+ assert.equal(
+ moment()
+ .add({ d: 5 })
+ .fromNow(),
+ 'za 5 dana',
+ 'in 5 days'
+ );
+});
+
+test('calendar day', function() {
+ var a = moment()
+ .hours(12)
+ .minutes(0)
+ .seconds(0);
+
+ assert.equal(moment(a).calendar(), 'danas u 12:00', 'today at the same time');
+ assert.equal(
+ moment(a)
+ .add({ m: 25 })
+ .calendar(),
+ 'danas u 12:25',
+ 'Now plus 25 min'
+ );
+ assert.equal(
+ moment(a)
+ .add({ h: 1 })
+ .calendar(),
+ 'danas u 13:00',
+ 'Now plus 1 hour'
+ );
+ assert.equal(
+ moment(a)
+ .add({ d: 1 })
+ .calendar(),
+ 'sutra u 12:00',
+ 'tomorrow at the same time'
+ );
+ assert.equal(
+ moment(a)
+ .subtract({ h: 1 })
+ .calendar(),
+ 'danas u 11:00',
+ 'Now minus 1 hour'
+ );
+ assert.equal(
+ moment(a)
+ .subtract({ d: 1 })
+ .calendar(),
+ 'juče u 12:00',
+ 'yesterday at the same time'
+ );
+});
+
+test('calendar next week', function() {
+ var i, m;
+
+ function makeFormat(d) {
+ switch (d.day()) {
+ case 0:
+ return '[u] [nedelju] [u] LT';
+ case 3:
+ return '[u] [sredu] [u] LT';
+ case 6:
+ return '[u] [subotu] [u] LT';
+ case 1:
+ case 2:
+ case 4:
+ case 5:
+ return '[u] dddd [u] LT';
+ }
+ }
+
+ for (i = 2; i < 7; i++) {
+ m = moment().add({ d: i });
+ assert.equal(
+ m.calendar(),
+ m.format(makeFormat(m)),
+ 'Today + ' + i + ' days current time'
+ );
+ m.hours(0)
+ .minutes(0)
+ .seconds(0)
+ .milliseconds(0);
+ assert.equal(
+ m.calendar(),
+ m.format(makeFormat(m)),
+ 'Today + ' + i + ' days beginning of day'
+ );
+ m.hours(23)
+ .minutes(59)
+ .seconds(59)
+ .milliseconds(999);
+ assert.equal(
+ m.calendar(),
+ m.format(makeFormat(m)),
+ 'Today + ' + i + ' days end of day'
+ );
+ }
+});
+
+test('calendar last week', function() {
+ var i, m;
+
+ function makeFormat(d) {
+ var lastWeekDay = [
+ '[prošle] [nedelje] [u] LT',
+ '[prošlog] [ponedeljka] [u] LT',
+ '[prošlog] [utorka] [u] LT',
+ '[prošle] [srede] [u] LT',
+ '[prošlog] [četvrtka] [u] LT',
+ '[prošlog] [petka] [u] LT',
+ '[prošle] [subote] [u] LT',
+ ];
+
+ return lastWeekDay[d.day()];
+ }
+
+ for (i = 2; i < 7; i++) {
+ m = moment().subtract({ d: i });
+ assert.equal(
+ m.calendar(),
+ m.format(makeFormat(m)),
+ 'Today - ' + i + ' days current time'
+ );
+ m.hours(0)
+ .minutes(0)
+ .seconds(0)
+ .milliseconds(0);
+ assert.equal(
+ m.calendar(),
+ m.format(makeFormat(m)),
+ 'Today - ' + i + ' days beginning of day'
+ );
+ m.hours(23)
+ .minutes(59)
+ .seconds(59)
+ .milliseconds(999);
+ assert.equal(
+ m.calendar(),
+ m.format(makeFormat(m)),
+ 'Today - ' + i + ' days end of day'
+ );
+ }
+});
+
+test('calendar all else', function() {
+ var weeksAgo = moment().subtract({ w: 1 }),
+ weeksFromNow = moment().add({ w: 1 });
+
+ assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago');
+ assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week');
+
+ weeksAgo = moment().subtract({ w: 2 });
+ weeksFromNow = moment().add({ w: 2 });
+
+ assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago');
+ assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks');
+});
+
+test('weeks year starting sunday formatted', function() {
+ assert.equal(
+ moment([2011, 11, 26]).format('w ww wo'),
+ '1 01 1.',
+ 'Dec 26 2011 should be week 1'
+ );
+ assert.equal(
+ moment([2012, 0, 1]).format('w ww wo'),
+ '1 01 1.',
+ 'Jan 1 2012 should be week 1'
+ );
+ assert.equal(
+ moment([2012, 0, 2]).format('w ww wo'),
+ '2 02 2.',
+ 'Jan 2 2012 should be week 2'
+ );
+ assert.equal(
+ moment([2012, 0, 8]).format('w ww wo'),
+ '2 02 2.',
+ 'Jan 8 2012 should be week 2'
+ );
+ assert.equal(
+ moment([2012, 0, 9]).format('w ww wo'),
+ '3 03 3.',
+ 'Jan 9 2012 should be week 3'
+ );
+});
diff --git a/packages/utilities/psammead-locales/moment/uk.js b/packages/utilities/psammead-locales/moment/uk.js
new file mode 100644
index 0000000000..13dbb0a213
--- /dev/null
+++ b/packages/utilities/psammead-locales/moment/uk.js
@@ -0,0 +1,10 @@
+var moment = require('moment');
+require('moment/locale/uk');
+
+moment.updateLocale('uk', {
+ longDateFormat: {
+ LL: 'D MMMM YYYY',
+ LLL: 'D MMMM YYYY, HH:mm',
+ LLLL: 'dddd, D MMMM YYYY, HH:mm',
+ },
+});
diff --git a/packages/utilities/psammead-locales/moment/uk.test.js b/packages/utilities/psammead-locales/moment/uk.test.js
new file mode 100644
index 0000000000..1b0ac319e4
--- /dev/null
+++ b/packages/utilities/psammead-locales/moment/uk.test.js
@@ -0,0 +1,512 @@
+import moment from 'moment';
+import './uk';
+
+moment.locale('uk');
+
+// This asset overrides the gunit assertion done in the moment codebase.
+// Format and styling of this file has been keep consistent with the official moment tests.
+// An example of these tests can be seen at https://github.com/moment/moment/blob/develop/src/test/locale/en-gb.js
+const assert = { equal: (val1, val2) => expect(val1).toEqual(val2) };
+
+test('parse', function() {
+ var tests = 'січень січ_лютий лют_березень бер_квітень квіт_травень трав_червень черв_липень лип_серпень серп_вересень вер_жовтень жовт_листопад лист_грудень груд'.split(
+ '_'
+ ),
+ i;
+ function equalTest(input, mmm, i) {
+ assert.equal(
+ moment(input, mmm).month(),
+ i,
+ input + ' should be month ' + (i + 1)
+ );
+ }
+ for (i = 0; i < 12; i++) {
+ tests[i] = tests[i].split(' ');
+ equalTest(tests[i][0], 'MMM', i);
+ equalTest(tests[i][1], 'MMM', i);
+ equalTest(tests[i][0], 'MMMM', i);
+ equalTest(tests[i][1], 'MMMM', i);
+ equalTest(tests[i][0].toLocaleLowerCase(), 'MMMM', i);
+ equalTest(tests[i][1].toLocaleLowerCase(), 'MMMM', i);
+ equalTest(tests[i][0].toLocaleUpperCase(), 'MMMM', i);
+ equalTest(tests[i][1].toLocaleUpperCase(), 'MMMM', i);
+ }
+});
+
+test('format', function() {
+ var a = [
+ ['dddd, Do MMMM YYYY, HH:mm:ss', 'неділя, 14-го лютого 2010, 15:25:50'],
+ ['ddd, h A', 'нд, 3 дня'],
+ ['M Mo MM MMMM MMM', '2 2-й 02 лютий лют'],
+ ['YYYY YY', '2010 10'],
+ ['D Do DD', '14 14-го 14'],
+ ['d do dddd ddd dd', '0 0-й неділя нд нд'],
+ ['DDD DDDo DDDD', '45 45-й 045'],
+ ['w wo ww', '7 7-й 07'],
+ ['h hh', '3 03'],
+ ['H HH', '15 15'],
+ ['m mm', '25 25'],
+ ['s ss', '50 50'],
+ ['a A', 'дня дня'],
+ ['DDDo [день року]', '45-й день року'],
+ ['LTS', '15:25:50'],
+ ['L', '14.02.2010'],
+ ['LL', '14 лютого 2010'],
+ ['LLL', '14 лютого 2010, 15:25'],
+ ['LLLL', 'неділя, 14 лютого 2010, 15:25'],
+ ],
+ b = moment(new Date(2010, 1, 14, 15, 25, 50, 125)),
+ i;
+ for (i = 0; i < a.length; i++) {
+ assert.equal(b.format(a[i][0]), a[i][1], a[i][0] + ' ---> ' + a[i][1]);
+ }
+});
+
+test('format meridiem', function() {
+ assert.equal(moment([2012, 11, 28, 0, 0]).format('A'), 'ночі', 'night');
+ assert.equal(moment([2012, 11, 28, 3, 59]).format('A'), 'ночі', 'night');
+ assert.equal(moment([2012, 11, 28, 4, 0]).format('A'), 'ранку', 'morning');
+ assert.equal(moment([2012, 11, 28, 11, 59]).format('A'), 'ранку', 'morning');
+ assert.equal(moment([2012, 11, 28, 12, 0]).format('A'), 'дня', 'afternoon');
+ assert.equal(moment([2012, 11, 28, 16, 59]).format('A'), 'дня', 'afternoon');
+ assert.equal(moment([2012, 11, 28, 17, 0]).format('A'), 'вечора', 'evening');
+ assert.equal(moment([2012, 11, 28, 23, 59]).format('A'), 'вечора', 'evening');
+});
+
+test('format ordinal', function() {
+ assert.equal(moment([2011, 0, 1]).format('DDDo'), '1-й', '1-й');
+ assert.equal(moment([2011, 0, 2]).format('DDDo'), '2-й', '2-й');
+ assert.equal(moment([2011, 0, 3]).format('DDDo'), '3-й', '3-й');
+ assert.equal(moment([2011, 0, 4]).format('DDDo'), '4-й', '4-й');
+ assert.equal(moment([2011, 0, 5]).format('DDDo'), '5-й', '5-й');
+ assert.equal(moment([2011, 0, 6]).format('DDDo'), '6-й', '6-й');
+ assert.equal(moment([2011, 0, 7]).format('DDDo'), '7-й', '7-й');
+ assert.equal(moment([2011, 0, 8]).format('DDDo'), '8-й', '8-й');
+ assert.equal(moment([2011, 0, 9]).format('DDDo'), '9-й', '9-й');
+ assert.equal(moment([2011, 0, 10]).format('DDDo'), '10-й', '10-й');
+
+ assert.equal(moment([2011, 0, 11]).format('DDDo'), '11-й', '11-й');
+ assert.equal(moment([2011, 0, 12]).format('DDDo'), '12-й', '12-й');
+ assert.equal(moment([2011, 0, 13]).format('DDDo'), '13-й', '13-й');
+ assert.equal(moment([2011, 0, 14]).format('DDDo'), '14-й', '14-й');
+ assert.equal(moment([2011, 0, 15]).format('DDDo'), '15-й', '15-й');
+ assert.equal(moment([2011, 0, 16]).format('DDDo'), '16-й', '16-й');
+ assert.equal(moment([2011, 0, 17]).format('DDDo'), '17-й', '17-й');
+ assert.equal(moment([2011, 0, 18]).format('DDDo'), '18-й', '18-й');
+ assert.equal(moment([2011, 0, 19]).format('DDDo'), '19-й', '19-й');
+ assert.equal(moment([2011, 0, 20]).format('DDDo'), '20-й', '20-й');
+
+ assert.equal(moment([2011, 0, 21]).format('DDDo'), '21-й', '21-й');
+ assert.equal(moment([2011, 0, 22]).format('DDDo'), '22-й', '22-й');
+ assert.equal(moment([2011, 0, 23]).format('DDDo'), '23-й', '23-й');
+ assert.equal(moment([2011, 0, 24]).format('DDDo'), '24-й', '24-й');
+ assert.equal(moment([2011, 0, 25]).format('DDDo'), '25-й', '25-й');
+ assert.equal(moment([2011, 0, 26]).format('DDDo'), '26-й', '26-й');
+ assert.equal(moment([2011, 0, 27]).format('DDDo'), '27-й', '27-й');
+ assert.equal(moment([2011, 0, 28]).format('DDDo'), '28-й', '28-й');
+ assert.equal(moment([2011, 0, 29]).format('DDDo'), '29-й', '29-й');
+ assert.equal(moment([2011, 0, 30]).format('DDDo'), '30-й', '30-й');
+
+ assert.equal(moment([2011, 0, 31]).format('DDDo'), '31-й', '31-й');
+});
+
+test('format month', function() {
+ var expected = 'січень січ_лютий лют_березень бер_квітень квіт_травень трав_червень черв_липень лип_серпень серп_вересень вер_жовтень жовт_листопад лист_грудень груд'.split(
+ '_'
+ ),
+ i;
+ for (i = 0; i < expected.length; i++) {
+ assert.equal(
+ moment([2011, i, 1]).format('MMMM MMM'),
+ expected[i],
+ expected[i]
+ );
+ }
+});
+
+test('format month case', function() {
+ var months = {
+ nominative: 'січень_лютий_березень_квітень_травень_червень_липень_серпень_вересень_жовтень_листопад_грудень'.split(
+ '_'
+ ),
+ accusative: 'січня_лютого_березня_квітня_травня_червня_липня_серпня_вересня_жовтня_листопада_грудня'.split(
+ '_'
+ ),
+ },
+ i;
+ for (i = 0; i < 12; i++) {
+ assert.equal(
+ moment([2011, i, 1]).format('D MMMM'),
+ '1 ' + months.accusative[i],
+ '1 ' + months.accusative[i]
+ );
+ assert.equal(
+ moment([2011, i, 1]).format('MMMM'),
+ months.nominative[i],
+ '1 ' + months.nominative[i]
+ );
+ }
+});
+
+test('format week', function() {
+ var expected = 'неділя нд нд_понеділок пн пн_вівторок вт вт_середа ср ср_четвер чт чт_п’ятниця пт пт_субота сб сб'.split(
+ '_'
+ ),
+ i;
+ for (i = 0; i < expected.length; i++) {
+ assert.equal(
+ moment([2011, 0, 2 + i]).format('dddd ddd dd'),
+ expected[i],
+ expected[i]
+ );
+ }
+});
+
+test('from', function() {
+ var start = moment([2007, 1, 28]);
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 44 }), true),
+ 'декілька секунд',
+ '44 seconds = seconds'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 45 }), true),
+ 'хвилина',
+ '45 seconds = a minute'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 89 }), true),
+ 'хвилина',
+ '89 seconds = a minute'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ s: 90 }), true),
+ '2 хвилини',
+ '90 seconds = 2 minutes'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 44 }), true),
+ '44 хвилини',
+ '44 minutes = 44 minutes'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 45 }), true),
+ 'годину',
+ '45 minutes = an hour'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 89 }), true),
+ 'годину',
+ '89 minutes = an hour'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ m: 90 }), true),
+ '2 години',
+ '90 minutes = 2 hours'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 5 }), true),
+ '5 годин',
+ '5 hours = 5 hours'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 21 }), true),
+ '21 година',
+ '21 hours = 21 hours'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 22 }), true),
+ 'день',
+ '22 hours = a day'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 35 }), true),
+ 'день',
+ '35 hours = a day'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ h: 36 }), true),
+ '2 дні',
+ '36 hours = 2 days'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 1 }), true),
+ 'день',
+ '1 day = a day'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 5 }), true),
+ '5 днів',
+ '5 days = 5 days'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 11 }), true),
+ '11 днів',
+ '11 days = 11 days'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 21 }), true),
+ '21 день',
+ '21 days = 21 days'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 25 }), true),
+ '25 днів',
+ '25 days = 25 days'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 26 }), true),
+ 'місяць',
+ '26 days = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 30 }), true),
+ 'місяць',
+ '30 days = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 43 }), true),
+ 'місяць',
+ '43 days = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 46 }), true),
+ '2 місяці',
+ '46 days = 2 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 74 }), true),
+ '2 місяці',
+ '75 days = 2 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 76 }), true),
+ '3 місяці',
+ '76 days = 3 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ M: 1 }), true),
+ 'місяць',
+ '1 month = a month'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ M: 5 }), true),
+ '5 місяців',
+ '5 months = 5 months'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 345 }), true),
+ 'рік',
+ '345 days = a year'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ d: 548 }), true),
+ '2 роки',
+ '548 days = 2 years'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ y: 1 }), true),
+ 'рік',
+ '1 year = a year'
+ );
+ assert.equal(
+ start.from(moment([2007, 1, 28]).add({ y: 5 }), true),
+ '5 років',
+ '5 years = 5 years'
+ );
+});
+
+test('suffix', function() {
+ assert.equal(moment(30000).from(0), 'за декілька секунд', 'prefix');
+ assert.equal(moment(0).from(30000), 'декілька секунд тому', 'suffix');
+});
+
+test('fromNow', function() {
+ assert.equal(
+ moment()
+ .add({ s: 30 })
+ .fromNow(),
+ 'за декілька секунд',
+ 'in seconds'
+ );
+ assert.equal(
+ moment()
+ .add({ d: 5 })
+ .fromNow(),
+ 'за 5 днів',
+ 'in 5 days'
+ );
+});
+
+test('calendar day', function() {
+ var a = moment()
+ .hours(12)
+ .minutes(0)
+ .seconds(0);
+
+ assert.equal(
+ moment(a).calendar(),
+ 'Сьогодні о 12:00',
+ 'today at the same time'
+ );
+ assert.equal(
+ moment(a)
+ .add({ m: 25 })
+ .calendar(),
+ 'Сьогодні о 12:25',
+ 'Now plus 25 min'
+ );
+ assert.equal(
+ moment(a)
+ .add({ h: 1 })
+ .calendar(),
+ 'Сьогодні о 13:00',
+ 'Now plus 1 hour'
+ );
+ assert.equal(
+ moment(a)
+ .add({ d: 1 })
+ .calendar(),
+ 'Завтра о 12:00',
+ 'tomorrow at the same time'
+ );
+ assert.equal(
+ moment(a)
+ .subtract({ h: 2 })
+ .calendar(),
+ 'Сьогодні о 10:00',
+ 'Now minus 2 hours'
+ );
+ assert.equal(
+ moment(a)
+ .subtract({ d: 1 })
+ .calendar(),
+ 'Вчора о 12:00',
+ 'yesterday at the same time'
+ );
+ // A special case for Ukrainian since 11 hours have different preposition
+ assert.equal(
+ moment(a)
+ .subtract({ h: 1 })
+ .calendar(),
+ 'Сьогодні об 11:00',
+ "same day at 11 o'clock"
+ );
+});
+
+test('calendar next week', function() {
+ var i, m;
+ for (i = 2; i < 7; i++) {
+ m = moment().add({ d: i });
+ assert.equal(
+ m.calendar(),
+ m.format('[У] dddd [о' + (m.hours() === 11 ? 'б' : '') + '] LT'),
+ 'Today + ' + i + ' days current time'
+ );
+ m.hours(0)
+ .minutes(0)
+ .seconds(0)
+ .milliseconds(0);
+ assert.equal(
+ m.calendar(),
+ m.format('[У] dddd [о] LT'),
+ 'Today + ' + i + ' days beginning of day'
+ );
+ m.hours(23)
+ .minutes(59)
+ .seconds(59)
+ .milliseconds(999);
+ assert.equal(
+ m.calendar(),
+ m.format('[У] dddd [о] LT'),
+ 'Today + ' + i + ' days end of day'
+ );
+ }
+});
+
+test('calendar last week', function() {
+ var i, m;
+
+ function makeFormat(d) {
+ switch (d.day()) {
+ case 0:
+ case 3:
+ case 5:
+ case 6:
+ return '[Минулої] dddd [о' + (d.hours() === 11 ? 'б' : '') + '] LT';
+ case 1:
+ case 2:
+ case 4:
+ return '[Минулого] dddd [о' + (d.hours() === 11 ? 'б' : '') + '] LT';
+ }
+ }
+
+ for (i = 2; i < 7; i++) {
+ m = moment().subtract({ d: i });
+ assert.equal(
+ m.calendar(),
+ m.format(makeFormat(m)),
+ 'Today - ' + i + ' days current time'
+ );
+ m.hours(0)
+ .minutes(0)
+ .seconds(0)
+ .milliseconds(0);
+ assert.equal(
+ m.calendar(),
+ m.format(makeFormat(m)),
+ 'Today - ' + i + ' days beginning of day'
+ );
+ m.hours(23)
+ .minutes(59)
+ .seconds(59)
+ .milliseconds(999);
+ assert.equal(
+ m.calendar(),
+ m.format(makeFormat(m)),
+ 'Today - ' + i + ' days end of day'
+ );
+ }
+});
+
+test('calendar all else', function() {
+ var weeksAgo = moment().subtract({ w: 1 }),
+ weeksFromNow = moment().add({ w: 1 });
+
+ assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '1 week ago');
+ assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 1 week');
+
+ weeksAgo = moment().subtract({ w: 2 });
+ weeksFromNow = moment().add({ w: 2 });
+
+ assert.equal(weeksAgo.calendar(), weeksAgo.format('L'), '2 weeks ago');
+ assert.equal(weeksFromNow.calendar(), weeksFromNow.format('L'), 'in 2 weeks');
+});
+
+test('weeks year starting sunday formatted', function() {
+ assert.equal(
+ moment([2011, 11, 26]).format('w ww wo'),
+ '1 01 1-й',
+ 'Dec 26 2011 should be week 1'
+ );
+ assert.equal(
+ moment([2012, 0, 1]).format('w ww wo'),
+ '1 01 1-й',
+ 'Jan 1 2012 should be week 1'
+ );
+ assert.equal(
+ moment([2012, 0, 2]).format('w ww wo'),
+ '2 02 2-й',
+ 'Jan 2 2012 should be week 2'
+ );
+ assert.equal(
+ moment([2012, 0, 8]).format('w ww wo'),
+ '2 02 2-й',
+ 'Jan 8 2012 should be week 2'
+ );
+ assert.equal(
+ moment([2012, 0, 9]).format('w ww wo'),
+ '3 03 3-й',
+ 'Jan 9 2012 should be week 3'
+ );
+});
diff --git a/packages/utilities/psammead-locales/package-lock.json b/packages/utilities/psammead-locales/package-lock.json
index 933a042871..ea4e88223e 100644
--- a/packages/utilities/psammead-locales/package-lock.json
+++ b/packages/utilities/psammead-locales/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@bbc/psammead-locales",
- "version": "2.6.0",
+ "version": "2.7.0",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/packages/utilities/psammead-locales/package.json b/packages/utilities/psammead-locales/package.json
index ff298bd5f5..80c1cce12d 100644
--- a/packages/utilities/psammead-locales/package.json
+++ b/packages/utilities/psammead-locales/package.json
@@ -1,6 +1,6 @@
{
"name": "@bbc/psammead-locales",
- "version": "2.6.0",
+ "version": "2.7.0",
"description": "A collection of locale configs, used in BBC World Service sites",
"repository": {
"type": "git",
diff --git a/packages/utilities/psammead-storybook-helpers/CHANGELOG.md b/packages/utilities/psammead-storybook-helpers/CHANGELOG.md
index 469658f3eb..4ef506c7ca 100644
--- a/packages/utilities/psammead-storybook-helpers/CHANGELOG.md
+++ b/packages/utilities/psammead-storybook-helpers/CHANGELOG.md
@@ -3,6 +3,7 @@
| Version | Description |
|---------|-------------|
+| 6.0.2 | [PR#2114](https://github.com/bbc/psammead/pull/2114) Update serbianCyr locale to `sr-cyrl`|
| 6.0.1 | [PR#2042](https://github.com/bbc/psammead/pull/1926) Update readme with changes to input provider |
| 6.0.0 | [PR#1926](https://github.com/bbc/psammead/pull/1926) Update input-provider to accept a single object rather than 4 arguments |
| 5.1.5 | [PR#1960](https://github.com/bbc/psammead/pull/1960) Change to <> |
diff --git a/packages/utilities/psammead-storybook-helpers/package-lock.json b/packages/utilities/psammead-storybook-helpers/package-lock.json
index 9a61bd78fc..c017c3dcba 100644
--- a/packages/utilities/psammead-storybook-helpers/package-lock.json
+++ b/packages/utilities/psammead-storybook-helpers/package-lock.json
@@ -1,6 +1,6 @@
{
"name": "@bbc/psammead-storybook-helpers",
- "version": "6.0.1",
+ "version": "6.0.2",
"lockfileVersion": 1,
"requires": true,
"dependencies": {
diff --git a/packages/utilities/psammead-storybook-helpers/package.json b/packages/utilities/psammead-storybook-helpers/package.json
index 0e95d24686..1c9c9f43fb 100644
--- a/packages/utilities/psammead-storybook-helpers/package.json
+++ b/packages/utilities/psammead-storybook-helpers/package.json
@@ -1,6 +1,6 @@
{
"name": "@bbc/psammead-storybook-helpers",
- "version": "6.0.1",
+ "version": "6.0.2",
"main": "dist/index.js",
"module": "esm/index.js",
"sideEffects": false,
diff --git a/packages/utilities/psammead-storybook-helpers/src/text-variants.js b/packages/utilities/psammead-storybook-helpers/src/text-variants.js
index dd3daa788a..2af41265a0 100644
--- a/packages/utilities/psammead-storybook-helpers/src/text-variants.js
+++ b/packages/utilities/psammead-storybook-helpers/src/text-variants.js
@@ -38,7 +38,7 @@ const LANGUAGE_VARIANTS = {
text:
'Medidas anunciadas no encontro entre Bolsonaro e Trump celebram aproximação com o governo americano - mas elas agora precisam passar pelo teste da concretização',
script: 'latinDiacritics',
- locale: 'pt',
+ locale: 'pt-br',
},
burmese: {
text: 'အောက်စဖို့ဒ် ဆရာတော် ပါမောက္ခ ဒေါက်တာအရှင်ဓမ္မသာမိ',
@@ -147,7 +147,7 @@ const LANGUAGE_VARIANTS = {
serbianCyr: {
text: 'Караџић се годинама крио пре него што је ухапшен 2008. године',
script: 'cyrillic',
- locale: 'sr',
+ locale: 'sr-cyrl',
},
serbianLat: {
text: 'Karadžić se godinama krio pre nego što je uhapšen 2008. godine',