Commit ef3bb235 authored by sod-ext's avatar sod-ext Committed by Anthony REY

A Brief History of Date

parent 9866f382
......@@ -10,4 +10,5 @@ include:
- local: "/ugly-trivia/.gitlab-ci.yml"
- local: "/borestop/.gitlab-ci.yml"
- local: "/java-pagination-seven/.gitlab-ci.yml"
- local: "/a-brief-history-of-date/.gitlab-ci.yml"
- local: "/mustache-replacer/.gitlab-ci.yml"
......@@ -43,3 +43,23 @@ stages:
- $PROJECT_FOLDER/target/jacoco-aggregate
expire_in: 1 day
coverage: "/([^%]+) %covered/"
.node:
image: node
stage: build
tags:
- docker
before_script:
- cd $PROJECT_FOLDER
script:
- npm i
- npm test
coverage: "/Statements.*?(.+)%/"
.node12:
extends: .node
image: node:12.19.0
.node14:
extends: .node
image: node:14.14.0
......@@ -14,7 +14,7 @@ Ce dépôt Git a pour but de partager les différents ateliers pouvant être ré
- [Chaîne Twitch](https://www.twitch.tv/ippontech)
- [Playlist Youtube (rediffusions)](https://www.youtube.com/playlist?list=PL6IFaLdAcgE3Uj2DYcbbxKJ-9moQe-g0F)
## Contenu des lives
## Kata Live Coding
| Nom | Type | Difficulté |
| --------------------------------------------------------------------------------------------------------------------- | ----------- | ---------- |
......@@ -30,4 +30,5 @@ Ce dépôt Git a pour but de partager les différents ateliers pouvant être ré
| [GreenIT: simple coup de peinture ou réelle démarche écologique ?](https://www.youtube.com/watch?v=liTuZZTCpGc) | Discussion | |
| [Une annonce pour recruter un crafter - Caroline, Chloé, Ianic et Colin](https://www.youtube.com/watch?v=E5AX6Ar1Fog) | Discussion | |
| [PadBowl](https://gitlab.com/cdamon/padbowl) | Application | Enervé |
| [A Brief History of Date](/a-brief-history-of-date) | Kata | Moyen |
| [Mustache Replacer](/mustache-replacer) | Kata | Facile |
module.exports = {
root: true,
env: {
node: true,
},
extends: [
'eslint:recommended',
'plugin:@typescript-eslint/recommended',
'plugin:import/errors',
'plugin:import/warnings',
'plugin:import/typescript',
],
plugins: ['prettier', '@typescript-eslint'],
rules: {
quotes: ['error', 'single', { avoidEscape: true }],
'comma-dangle': [
'error',
{
arrays: 'always-multiline',
objects: 'always-multiline',
imports: 'always-multiline',
exports: 'always-multiline',
functions: 'never',
},
],
'import/order': [
'error',
{
alphabetize: {
order: 'asc',
caseInsensitive: true,
},
'newlines-between': 'always',
},
],
'prettier/prettier': [
'error',
{
singleQuote: true,
trailingComma: 'es5',
printWidth: 140,
},
],
},
settings: {
'import/resolver': {
typescript: {
alwaysTryTypes: true,
},
},
'import/core-modules': ['sinon'],
},
parserOptions: {
parser: '@typescript-eslint/parser',
},
overrides: [
{
files: ['**/__tests__/*.{j,t}s?(x)', '**/*.spec.{j,t}s?(x)'],
env: {
jest: true,
},
},
{
files: ['**/*.ts', '**/*.tsx'],
rules: {
'no-unused-vars': ['off'],
'no-undef': ['off'],
},
},
],
};
package-a-brief-history-of-date:
variables:
PROJECT_FOLDER: "a-brief-history-of-date"
TZ: "Europe/Paris"
extends: .node14
only:
refs:
- master
- merge_requests
changes:
- ".gitlab-common-ci.yml"
- "a-brief-history-of-date/**/*"
# A Brief History of Date
Exploration de l'API Date de JavaScript pour découvrir les problématiques associées. Propositions de représentation des dates pour les manipuler.
- **Auteurs** : Sébastien ODDO et Anthony REY
- **Date** : 06/10/2020
- **Langage** : TypeScript
- **Niveau** : Moyen
- **Replay** : [A Brief History of Date par Sébastien et Anthony](https://www.youtube.com/watch?v=6n4rPIVLYQw)
module.exports = {
roots: ['<rootDir>/src'],
transform: {
'^.+\\.tsx?$': 'ts-jest',
},
testRegex: '(/__tests__/.*|(\\.|/)(test|spec))\\.tsx?$',
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
collectCoverage: true,
collectCoverageFrom: ['src/**/*.ts', '!src/**/*.spec.ts'],
coverageReporters: ['html', 'text-summary'],
};
This source diff could not be displayed because it is too large. You can view the blob instead.
{
"name": "template-ts-kata",
"version": "1.0.0",
"description": "Template TS kata",
"main": "src/index.ts",
"dependencies": {
"@types/jest": "^26.0.14",
"@typescript-eslint/eslint-plugin": "^4.1.1",
"@typescript-eslint/parser": "^4.1.1",
"eslint": "^7.9.0",
"eslint-import-resolver-typescript": "^2.3.0",
"eslint-plugin-import": "^2.22.0",
"eslint-plugin-prettier": "^3.1.4",
"jest": "^26.4.2",
"moment": "^2.29.1",
"prettier": "^2.1.2",
"ts-jest": "^26.3.0",
"typescript": "^4.0.2"
},
"scripts": {
"test": "jest",
"test:watch": "jest --watch",
"test:watch:all": "jest --watchAll",
"eslint:ci": "eslint './**/*.{ts,js}'",
"eslint": "eslint './**/*.{ts,js}' --fix"
},
"author": "Anthony REY",
"license": "MIT"
}
import * as moment from 'moment';
const pad = (number: number): string => number.toString().padStart(2, '0');
class DateTime {
private readonly utcYear: number;
private readonly utcMonth: number;
private readonly utcDay: number;
private readonly utcHours: number;
private readonly utcMinutes: number;
private readonly year: number;
private readonly month: number;
private readonly day: number;
private readonly hours: number;
private readonly minutes: number;
private constructor(isoDate: string) {
const date = new Date(isoDate);
this.utcYear = date.getUTCFullYear();
this.utcMonth = date.getUTCMonth() + 1;
this.utcDay = date.getUTCDate();
this.utcHours = date.getUTCHours();
this.utcMinutes = date.getUTCMinutes();
this.year = date.getFullYear();
this.month = date.getMonth() + 1;
this.day = date.getDate();
this.hours = date.getHours();
this.minutes = date.getMinutes();
}
static of(isoDate: string): DateTime {
return new DateTime(isoDate);
}
getUtcMonth(): number {
return this.utcMonth;
}
getUtcDay(): number {
return this.utcDay;
}
getUtcHours(): number {
return this.utcHours;
}
getUtcMinutes(): number {
return this.utcMinutes;
}
getUtcYear(): number {
return this.utcYear;
}
toHuman(): string {
return `${pad(this.day)}/${pad(this.month)}/${this.year} ${pad(this.hours)}:${pad(this.minutes)}`;
}
}
const ISO_DATE = '2020-10-06T19:10:00Z';
describe('DateTime', () => {
it('Should have an utc year', () => {
expect(DateTime.of(ISO_DATE).getUtcYear()).toBe(2020);
});
it('Should have an utc month', () => {
expect(DateTime.of(ISO_DATE).getUtcMonth()).toBe(10);
});
it('Should have an utc day', () => {
expect(DateTime.of(ISO_DATE).getUtcDay()).toBe(6);
});
it('Should have an utc hour', () => {
expect(DateTime.of(ISO_DATE).getUtcHours()).toBe(19);
});
it('Should have an utc minutes', () => {
expect(DateTime.of(ISO_DATE).getUtcMinutes()).toBe(10);
});
it('Should display in human format', () => {
expect(DateTime.of(ISO_DATE).toHuman()).toBe(moment(ISO_DATE).format('DD/MM/YYYY HH:mm'));
});
});
describe('Explore the Date API', () => {
it('should return the month of a Date', () => {
const date = new Date('2020-10-06');
const month = date.getUTCMonth();
expect(month).toBe(9);
});
it('should return the hour of a Date', () => {
const date = new Date('2020-10-06');
const hour = date.getUTCHours();
expect(hour).toBe(0);
});
it('should return the Date depending on timezone', () => {
const date = new Date('2019-12-31T23:45:00Z');
const day = date.getDate();
const month = date.getMonth() + 1;
const year = date.getFullYear();
expect(day).toBe(1);
expect(month).toBe(1);
expect(year).toBe(2020);
});
});
import { LocalDate } from './local-date';
describe('LocalDate', () => {
const LOCAL_DATE = new LocalDate('2020-10-06');
it('should return the month', () => {
expect(LOCAL_DATE.getMonth()).toBe(10);
});
it('should return the year', () => {
expect(LOCAL_DATE.getYear()).toBe(2020);
});
it('should return the day', () => {
expect(LOCAL_DATE.getDay()).toBe(6);
});
it('cannot create a date with bad iso format', () => {
expect(() => new LocalDate('20-aa-06')).toThrow('The date is malformed.');
});
it('should display the date in human format', () => {
expect(LOCAL_DATE.toHumanFormat()).toBe('06/10/2020');
});
it("cannot create a date which doesn't exist", () => {
expect(() => new LocalDate('2020-02-31')).toThrow("The date doesn't exist.");
});
});
import moment = require('moment');
const DATE_PATTERN = /^\d{4}-\d{2}-\d{2}$/;
const padTwoCharacters = (digit: number): string => digit.toString().padStart(2, '0');
const assertDateFormat = (isoDate: string): void => {
if (!DATE_PATTERN.test(isoDate)) {
throw new Error('The date is malformed.');
}
};
const assertValidDate = (isoDate: string): void => {
if (!moment(isoDate, 'YYYY-MM-DD', true).isValid()) {
throw new Error("The date doesn't exist.");
}
};
export class LocalDate {
private month: number;
private year: number;
private day: number;
constructor(isoDate: string) {
assertDateFormat(isoDate);
assertValidDate(isoDate);
[this.year, this.month, this.day] = isoDate.split('-').map((member) => parseInt(member, 10));
}
public getMonth(): number {
return this.month;
}
public getYear(): number {
return this.year;
}
public getDay(): number {
return this.day;
}
public toHumanFormat(): string {
return `${padTwoCharacters(this.day)}/${padTwoCharacters(this.month)}/${this.year}`;
}
}
{
"compilerOptions": {
"target": "ES2019",
"module": "commonjs",
"noImplicitAny": true,
"removeComments": true,
"preserveConstEnums": true,
"outFile": "dist/main.js",
"sourceMap": true
},
"include": [
"src/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment