Skip to content

Commit 4c90e27

Browse files
authored
Merge pull request #12 from levisantosp/main
2 parents 11a8fb4 + 5f269a7 commit 4c90e27

File tree

5 files changed

+158
-13
lines changed

5 files changed

+158
-13
lines changed

.changeset/wise-comics-buy.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"enhanced-ms": minor
3+
---
4+
5+
Add support for Portuguese

README.md

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -50,19 +50,20 @@ As mentioned above, `enhanced-ms` is an enhanced version of the popular [`ms`](h
5050

5151
The currently supported languages include:
5252

53-
| Language | Key |
54-
| -------------------- | ----- |
55-
| English (default) | en |
56-
| German | de |
57-
| Russian | ru |
58-
| Māori | mi |
59-
| Spanish | es |
60-
| Dutch | nl |
61-
| Italian | it |
62-
| French | fr |
63-
| Czech | cs |
64-
| Polish | pl |
65-
| Chinese (Simplified) | zh-CN |
53+
| Language | Key |
54+
| --------------------- | ----- |
55+
| English (default) | en |
56+
| German | de |
57+
| Russian | ru |
58+
| Māori | mi |
59+
| Spanish | es |
60+
| Dutch | nl |
61+
| Italian | it |
62+
| French | fr |
63+
| Czech | cs |
64+
| Polish | pl |
65+
| Portuguese | pt |
66+
| Chinese (Simplified) | zh-CN |
6667

6768
You can help by adding support for more languages.
6869

src/languages/index.ts

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ import it from './it';
99
import mi from './mi';
1010
import nl from './nl';
1111
import pl from './pl';
12+
import pt from './pt';
1213
import ru from './ru';
1314
import zhCN from './zh-CN';
1415

@@ -23,6 +24,7 @@ type Locale =
2324
| 'mi'
2425
| 'nl'
2526
| 'pl'
27+
| 'pt'
2628
| 'ru'
2729
| 'zh-CN';
2830
type Languages = Record<Locale, LanguageDefinition>;
@@ -36,6 +38,7 @@ export const languages: Languages = {
3638
mi,
3739
nl,
3840
pl,
41+
pt,
3942
ru,
4043
'zh-CN': zhCN,
4144
};

src/languages/pt.ts

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
export default {
2+
decimal: ',',
3+
and: 'e',
4+
5+
units: {
6+
nanosecond: {
7+
name: (c) => (c === 1 ? 'nanossegundo' : 'nanossegundos'),
8+
abbreviation: 'ns',
9+
matches: ['nanossegundo', 'nanossegundos', 'ns'],
10+
},
11+
microsecond: {
12+
name: (c) => (c === 1 ? 'microssegundo' : 'microssegundos'),
13+
abbreviation: 'μs',
14+
matches: ['microssegundo', 'microssegundos', 'μs'],
15+
},
16+
millisecond: {
17+
name: (c) => (c === 1 ? 'milissegundo' : 'milissegundos'),
18+
abbreviation: 'ms',
19+
matches: ['milissegundo', 'milissegundos', 'ms'],
20+
},
21+
second: {
22+
name: (c) => (c === 1 ? 'segundo' : 'segundos'),
23+
abbreviation: 's',
24+
matches: ['segundo', 'segundos', 's'],
25+
},
26+
minute: {
27+
name: (c) => (c === 1 ? 'minuto' : 'minutos'),
28+
abbreviation: 'm',
29+
matches: ['minuto', 'minutos', 'm'],
30+
},
31+
hour: {
32+
name: (c) => (c === 1 ? 'hora' : 'horas'),
33+
abbreviation: 'h',
34+
matches: ['hora', 'horas', 'h'],
35+
},
36+
day: {
37+
name: (c) => (c === 1 ? 'dia' : 'dias'),
38+
abbreviation: 'd',
39+
matches: ['dia', 'dias', 'd'],
40+
},
41+
week: {
42+
name: (c) => (c === 1 ? 'semana' : 'semanas'),
43+
abbreviation: 'sem',
44+
matches: ['semana', 'semanas', 'sem'],
45+
},
46+
month: {
47+
name: (c) => (c === 1 ? 'mês' : 'meses'),
48+
abbreviation: 'me',
49+
matches: ['mês', 'meses', 'me'],
50+
},
51+
year: {
52+
name: (c) => (c === 1 ? 'ano' : 'anos'),
53+
abbreviation: 'a',
54+
matches: ['ano', 'anos', 'a'],
55+
},
56+
decade: {
57+
name: (c) => (c === 1 ? 'década' : 'décadas'),
58+
abbreviation: 'dec',
59+
matches: ['década', 'décadas', 'dec'],
60+
},
61+
century: {
62+
name: (c) => (c === 1 ? 'século' : 'séculos'),
63+
abbreviation: 'sec',
64+
matches: ['século', 'séculos', 'sec'],
65+
},
66+
millennium: {
67+
name: (c) => (c === 1 ? 'milênio' : 'milênios'),
68+
abbreviation: 'mil',
69+
matches: ['milênio', 'milênios', 'mil'],
70+
},
71+
},
72+
} satisfies import('./helpers/definition-types').LanguageDefinition;

tests/pt.test.ts

Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import { createMs } from 'enhanced-ms';
2+
import { describe, expect, it } from 'vitest';
3+
4+
const ms = createMs({ language: 'pt' });
5+
6+
describe('Portuguese', () => {
7+
describe('format milliseconds', () => {
8+
it('formats milliseconds with default options', () => {
9+
expect(ms(90061)).toBe('1 minuto 30 segundos');
10+
expect(ms(90061000)).toBe('1 dia 1 hora 1 minuto 1 segundo');
11+
});
12+
13+
it('returns null for sub one second with default options', () => {
14+
expect(ms(0)).toBeNull();
15+
});
16+
17+
it('format using short preset', () => {
18+
expect(ms(90061, 'short')).toBe('1m 30s');
19+
expect(ms(90061000, 'short')).toBe('1d 1h');
20+
});
21+
22+
it('format using colon notation preset', () => {
23+
expect(ms(90061, 'colonNotation')).toBe('01:30');
24+
expect(ms(90061000, 'colonNotation')).toBe('25:01:01');
25+
});
26+
27+
it('formats with use abbreviations', () => {
28+
const options = { useAbbreviations: true };
29+
expect(ms(90061, options)).toBe('1m 30s');
30+
expect(ms(90061000, options)).toBe('1d 1h 1m 1s');
31+
});
32+
33+
it('formats with unit limit', () => {
34+
const options = { unitLimit: 1 };
35+
expect(ms(90061, options)).toBe('1 minuto');
36+
expect(ms(90061000, options)).toBe('1 dia');
37+
});
38+
});
39+
40+
describe('parse duration', () => {
41+
it('parses durations', () => {
42+
expect(ms('1 minuto 30 segundos')).toBe(90000);
43+
expect(ms('1m 30s')).toBe(90000);
44+
expect(ms('1 minuto 30 segundos 61 milissegundos')).toBe(90061);
45+
expect(ms('1m 30s 61ms')).toBe(90061);
46+
});
47+
48+
it('parses portuguese-specific unit names and abbreviations', () => {
49+
expect(ms('2 meses')).toBe(2 * 2_628_000_000);
50+
expect(ms('2 semanas')).toBe(2 * 604_800_000);
51+
expect(ms('2sem')).toBe(2 * 604_800_000);
52+
});
53+
54+
it('parses accented portuguese unit names correctly', () => {
55+
expect(ms('2 séculos')).toBe(2 * 3_153_600_000_000);
56+
expect(ms('2 milênios')).toBe(2 * 31_536_000_000_000);
57+
});
58+
59+
it('returns zero for invalid durations', () => {
60+
expect(ms('nyr9341')).toBe(0);
61+
expect(ms('o4utrc89nyt')).toBe(0);
62+
});
63+
});
64+
});

0 commit comments

Comments
 (0)