chore(utils): ports over utils from the WPF app
This commit is contained in:
parent
949e33f06f
commit
7dc4bd8a11
4 changed files with 129 additions and 0 deletions
50
src/lib/utils/conversions.test.ts
Normal file
50
src/lib/utils/conversions.test.ts
Normal file
|
|
@ -0,0 +1,50 @@
|
|||
import { describe, it, expect } from 'vitest';
|
||||
import { cmToFeetInches, feetInchesToCm, kgToLb, lbToKg } from './conversions';
|
||||
|
||||
describe('cmToFeetInches', () => {
|
||||
it('converts 180 cm', () => {
|
||||
expect(cmToFeetInches(180)).toBe('5\'11"');
|
||||
});
|
||||
|
||||
it('converts 152 cm', () => {
|
||||
expect(cmToFeetInches(152)).toBe('5\'0"');
|
||||
});
|
||||
|
||||
it('converts 0 cm', () => {
|
||||
expect(cmToFeetInches(0)).toBe('0\'0"');
|
||||
});
|
||||
|
||||
it('converts 30 cm (just inches)', () => {
|
||||
expect(cmToFeetInches(30)).toBe('1\'0"');
|
||||
});
|
||||
});
|
||||
|
||||
describe('feetInchesToCm', () => {
|
||||
it('converts 5\'11" back', () => {
|
||||
expect(feetInchesToCm(5, 11)).toBeCloseTo(180.34, 0);
|
||||
});
|
||||
|
||||
it('converts 0\'0"', () => {
|
||||
expect(feetInchesToCm(0, 0)).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('kgToLb', () => {
|
||||
it('converts 75 kg', () => {
|
||||
expect(kgToLb(75)).toBeCloseTo(165.35, 0);
|
||||
});
|
||||
|
||||
it('converts 0 kg', () => {
|
||||
expect(kgToLb(0)).toBe(0);
|
||||
});
|
||||
});
|
||||
|
||||
describe('lbToKg', () => {
|
||||
it('converts 165 lb', () => {
|
||||
expect(lbToKg(165)).toBeCloseTo(74.84, 0);
|
||||
});
|
||||
|
||||
it('converts 0 lb', () => {
|
||||
expect(lbToKg(0)).toBe(0);
|
||||
});
|
||||
});
|
||||
22
src/lib/utils/conversions.ts
Normal file
22
src/lib/utils/conversions.ts
Normal file
|
|
@ -0,0 +1,22 @@
|
|||
const CM_PER_INCH = 2.54;
|
||||
const INCHES_PER_FOOT = 12;
|
||||
const LB_PER_KG = 2.20462;
|
||||
|
||||
export function cmToFeetInches(cm: number): string {
|
||||
const totalInches = Math.round(cm / CM_PER_INCH);
|
||||
const feet = Math.floor(totalInches / INCHES_PER_FOOT);
|
||||
const inches = totalInches % INCHES_PER_FOOT;
|
||||
return `${feet}'${inches}"`;
|
||||
}
|
||||
|
||||
export function feetInchesToCm(feet: number, inches: number): number {
|
||||
return (feet * INCHES_PER_FOOT + inches) * CM_PER_INCH;
|
||||
}
|
||||
|
||||
export function kgToLb(kg: number): number {
|
||||
return kg * LB_PER_KG;
|
||||
}
|
||||
|
||||
export function lbToKg(lb: number): number {
|
||||
return lb / LB_PER_KG;
|
||||
}
|
||||
33
src/lib/utils/dates.test.ts
Normal file
33
src/lib/utils/dates.test.ts
Normal file
|
|
@ -0,0 +1,33 @@
|
|||
import { describe, it, expect } from 'vitest';
|
||||
import { icYear, formatICDate } from './dates';
|
||||
|
||||
describe('icYear', () => {
|
||||
it('adds 442 to the real year', () => {
|
||||
expect(icYear(2026)).toBe(2468);
|
||||
});
|
||||
|
||||
it('works for other years', () => {
|
||||
expect(icYear(2000)).toBe(2442);
|
||||
});
|
||||
});
|
||||
|
||||
describe('formatICDate', () => {
|
||||
it('formats with ordinal suffixes', () => {
|
||||
expect(formatICDate(new Date(2026, 2, 1))).toBe('March 1st, 2468');
|
||||
expect(formatICDate(new Date(2026, 2, 2))).toBe('March 2nd, 2468');
|
||||
expect(formatICDate(new Date(2026, 2, 3))).toBe('March 3rd, 2468');
|
||||
expect(formatICDate(new Date(2026, 2, 4))).toBe('March 4th, 2468');
|
||||
});
|
||||
|
||||
it('handles 11th, 12th, 13th', () => {
|
||||
expect(formatICDate(new Date(2026, 0, 11))).toBe('January 11th, 2468');
|
||||
expect(formatICDate(new Date(2026, 0, 12))).toBe('January 12th, 2468');
|
||||
expect(formatICDate(new Date(2026, 0, 13))).toBe('January 13th, 2468');
|
||||
});
|
||||
|
||||
it('handles 21st, 22nd, 23rd', () => {
|
||||
expect(formatICDate(new Date(2026, 5, 21))).toBe('June 21st, 2468');
|
||||
expect(formatICDate(new Date(2026, 5, 22))).toBe('June 22nd, 2468');
|
||||
expect(formatICDate(new Date(2026, 5, 23))).toBe('June 23rd, 2468');
|
||||
});
|
||||
});
|
||||
24
src/lib/utils/dates.ts
Normal file
24
src/lib/utils/dates.ts
Normal file
|
|
@ -0,0 +1,24 @@
|
|||
const IC_OFFSET = 442;
|
||||
|
||||
const MONTHS = [
|
||||
'January', 'February', 'March', 'April', 'May', 'June',
|
||||
'July', 'August', 'September', 'October', 'November', 'December'
|
||||
];
|
||||
|
||||
function ordinal(n: number): string {
|
||||
if (n >= 11 && n <= 13) return n + 'th';
|
||||
switch (n % 10) {
|
||||
case 1: return n + 'st';
|
||||
case 2: return n + 'nd';
|
||||
case 3: return n + 'rd';
|
||||
default: return n + 'th';
|
||||
}
|
||||
}
|
||||
|
||||
export function icYear(realYear: number): number {
|
||||
return realYear + IC_OFFSET;
|
||||
}
|
||||
|
||||
export function formatICDate(date: Date): string {
|
||||
return `${MONTHS[date.getMonth()]} ${ordinal(date.getDate())}, ${icYear(date.getFullYear())}`;
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue