Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: new concept exercise - appointment-time #1926

Closed
Closed
8 changes: 8 additions & 0 deletions config.json
Original file line number Diff line number Diff line change
Expand Up @@ -255,6 +255,14 @@
"concepts": ["classes"],
"prerequisites": ["objects", "functions", "conditionals-ternary"],
"status": "beta"
},
{
"slug": "appointment-time",
"name": "Appointment Time",
"uuid": "0f694053-a388-457f-89ca-f49be4560469",
"concepts": ["dates"],
"prerequisites": ["classes", "conditionals"],
"status": "beta"
}
],
"practice": [
Expand Down
16 changes: 8 additions & 8 deletions exercises/concept/amusement-park/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,15 +10,15 @@
"directory": "exercises/concept/amusement-park"
},
"devDependencies": {
"@babel/core": "^7.19.1",
"@exercism/babel-preset-javascript": "^0.1.2",
"@babel/core": "^7.20.5",
"@exercism/babel-preset-javascript": "^0.2.1",
"@exercism/eslint-config-javascript": "^0.6.0",
"@types/jest": "^29.0.3",
"@types/node": "^18.7.23",
"babel-jest": "^29.0.3",
"core-js": "^3.25.3",
"eslint": "^8.24.0",
"jest": "^29.0.3"
"@types/jest": "^29.2.4",
"@types/node": "^18.11.15",
"babel-jest": "^29.2.2",
"core-js": "~3.26.1",
"eslint": "^8.29.0",
"jest": "^29.3.1"
},
"dependencies": {},
"scripts": {
Expand Down
16 changes: 8 additions & 8 deletions exercises/concept/annalyns-infiltration/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,15 @@
"directory": "exercises/concept/annalyns-infiltration"
},
"devDependencies": {
"@babel/core": "^7.19.1",
"@exercism/babel-preset-javascript": "^0.1.2",
"@babel/core": "^7.20.5",
"@exercism/babel-preset-javascript": "^0.2.1",
"@exercism/eslint-config-javascript": "^0.6.0",
"@types/jest": "^29.0.3",
"@types/node": "^18.7.23",
"babel-jest": "^29.0.3",
"core-js": "^3.25.3",
"eslint": "^8.24.0",
"jest": "^29.0.3"
"@types/jest": "^29.2.4",
"@types/node": "^18.11.15",
"babel-jest": "^29.2.2",
"core-js": "~3.26.1",
"eslint": "^8.29.0",
"jest": "^29.3.1"
},
"dependencies": {},
"scripts": {
Expand Down
25 changes: 25 additions & 0 deletions exercises/concept/appointment-time/.docs/hints.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
# Hints

## 1. Create an appointment

- `new Date()` can be used to create new date. You can pass timestamp to create specific date.
- `Date.now()` gives you current timestamp.
- A day consist of 24 hour. An hour consist of 60 minutes. A minute consist of 60 seconds. A second consist of 1000 milliseconds. In order to get timestamp of `n` days later from current date, you can sum current timestamp and `n * 24 * 60 * 60 * 1000`.

## 2. Get details of an appointment

- Date object has [built-in methods][mdn-date-methods] to get different parts of the date.

## 3. Update an appointment with given options

- Date object has [built-in methods][mdn-date-methods] to modify date.

## 4. Get available times between two appointment

- General subtraction between two dates will give you the timestamp between the two dates.

## 5. Check if an appointment is now valid or not

- Conditional operators will help you to decide which date is bigger or smaller between two dates.

[mdn-date-methods]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date#instance_methods
54 changes: 54 additions & 0 deletions exercises/concept/appointment-time/.docs/instructions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
# Instructions

In this exercise you will code some functions in order to manage appointments.

## 1. Create an appointment

Create an appointment `x` days from now at current time.
The function takes `x` as parameter and return the appointment time of `x` days from now.

```javascript
createAppointment(4);
// If current time is Sun Oct 05 2022 23:28:43 GMT+0600 (Bangladesh Standard Time) then the function will return Sun Oct 09 2022 23:28:43 GMT+0600 (Bangladesh Standard Time)
```

## 2. Get details of an appointment

The function takes an appointment time as argument and return a string containing information like below.

```javascript
getAppointment('24 April 2022 10:15 AM');
// => { year: 2022, month: 3, date: 24, hour: 10, minute: 15 }
```

## 3. Update an appointment with given options

The function will receive first argument as appointment time and second argument of object of some options.
You have to update the appointment according to the options in the object and return the new appointment date.
The options object could have multiple options.

```javascript
updateAppointment('09 February 2022 10:20 am', { month: 6 });
// => { year: 2022, month: 6, date: 9, hour: 10, minute: 20 }
```

## 4. Get available times between two appointment

The function will receive two appointment times as parameter.
You have to return the difference between those two times in `ms`.

```javascript
availableTimes('12 December 2022 10:20 am', '18 December 2022 9:30 am');
// => 515400000
```

## 5. Check if an appointment is now valid or not

The function receives two arguments - appointment time and current time.
If the appointment time is less than the current time then the appointment is not valid anymore, and you should return `The appointment is not valid anymore.`
If not, the appointment is valid, and you should return `The appointment is valid.`

```javascript
isValid('12 February 2022', '9 February 2022');
// => The appointment is valid.
```
192 changes: 192 additions & 0 deletions exercises/concept/appointment-time/.docs/introduction.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,192 @@
# Introduction

JavaScript has a built-in object `Date` which stores date and time, and provides methods for their management.

## Creation

A `Date` object in an instance of the `Date` class. It can be created without passing any arguments to the constructor function. This results in a `Date` object that represents the current date and time:

```javascript
const now = new Date();
// => Thu Apr 14 2022 11:46:08 GMT+0530 (India Standard Time)

// Shows current day, date and time in your time zone.
```

However, different types of arguments can also be used to create date object, as follows:

### Timestamp value

> A timestamp is an integer number representing the number of **milliseconds** that has passed since **Jan 1st of 1970 [UTC][utc-defn]+0**, however, _with reference to your local time zone._
> This can be used as an argument for the Date object.
>
> ```javascript
> const Jan01_1970 = new Date(0);
> // 0 means 01.01.1970 UTC+0
>
> const Jan02_1970 = new Date(24 * 3600 * 1000);
> // adding 24 hours, we get 02.01.1970 UTC+0
>
> // Note that the objects created here would show the corresponding time in your time zone.
> ```
>
> [^1]

### Timestamp string

You can pass a string value representing a date to the `Date` constructor.
The string needs to follow a format that is recognized by the `Date.parse()` method.
You will learn more about this below.

### Date object

An existing date object can also be used as an argument.
This makes a copy of the existing `Date` object with the same date and time.

```javascript
const t1 = new Date();
const t2 = new Date(t1);

// Values of t1 and t2 will be the same.
```

### Individual date and time component values

> Given at least a year and month, this form of `Date()` returns a `Date` object whose component values _(year, month, day, hour, minute, second, and millisecond)_ all come from the following parameters.
> Any missing fields are given the lowest possible value (1 for day and 0 for every other component).
> The parameter values are all evaluated against the _local time zone, rather than UTC_.
>
> - `year`: Integer values from 0 to 99 map to the years 1900 to 1999.
> All other values are the actual year.
> - `monthIndex`: Integer value representing the month, beginning with _0 for January to 11 for December_.
> If a value greater than 11 is passed in, then those months will be added to the date.
> For example, new Date(1990, 12, 1) will return January 1st, 1991.
> - `day` (Optional): Integer value representing the day of the month.
> The default is 1.
> - `hours` (Optional): Integer value between 0 and 23 representing the hour of the day.
> Defaults to 0.
> - `minutes` (Optional): Integer value representing the minute segment of a time.
> The default is 0 minutes past the hour.
> - `seconds` (Optional): Integer value representing the second segment of a time.
> The default is 0 seconds past the minute.
> - `milliseconds` (Optional): Integer value representing the millisecond segment of a time.
> The default is 0 milliseconds past the second.
>
> [^2]

```javascript
const date1 = new Date(95, 11, 17);
// Creates Date for Dec 17 1995 00:00 if your local timezone is equivalent to UTC.

const date2 = new Date(2013, 12, 5, 13, 24, 0);
// Creates Date for Jan 5 2014 13:24 if your local timezone is equivalent to UTC.
```

## `Date.parse()`

`Date.parse()` takes **string as a input and returns a timestamp** (number of milliseconds from 1 Jan 1970 UTC+0), provided the string is in the format YYYY-MM-DDTHH:mm:ss.sssZ, where:

> - `YYYY-MM-DD` - is the date: year-month-day.
> - `T` - The character "T" is used as the delimiter
> - `HH:mm:ss.sss` - is the time: hours, minutes, seconds and milliseconds.
> - `Z` - This _optional_ part denotes the time zone.
> If `Z` is present, the `Date` will be set to UTC.
> If `Z` is not present, it will be Local Time.
>
> If the format is invalid, `NaN` is returned. [^3]

Shorter variants are also possible, like `YYYY-MM-DD` or `YYYY-MM` or even `YYYY`. However, note that these variants **set the `Date` to UTC**, even though `Z` not mentioned.
To understand what exactly happens check out [this section][mdn-diff-assumed-timezone] of a MDN page.

```exercism/caution
The use of `Date.parse()` (and the timestamp string method which works similarly) is strongly discouraged due to browser differences and inconsistencies. [^4]
```

## Accessing `Date` components

The following are the methods to access the year, month and so on from the Date object:

> - `getFullYear()`- Get the year (4 digits)
> - `getMonth()`- Get the month, from 0 to 11.
> - `getDate()`- Get the day of month, from 1 to 31.
> - `getHours()`, `getMinutes()`, `getSeconds()`, `getMilliseconds()`- Get the corresponding time components.
> - `getDay()`- Get the day of week, from 0 (Sunday) to 6 (Saturday).
> - `getTime()`- Get the number of milliseconds passed since 01.01.1970 UTC.
>
> [^5]

```javascript
const date0 = new Date(0); //Jan 1 1970 00:00:00
let month = date0.getMonth()); // => 0; as Jan is the month
let date = date0.getDay(); // Find out which day the new year of 1970 was!

const date1 = new Date(2020, 11, 13, 5); // Dec 13 2020 5:00:00
let millsecs = date1.getTime(); // find out how many have milliseconds passed since Jan 1 1890!
```

## Modifying `Date` components

The following methods allow to modify date/time components :

> - `setFullYear(year, [month], [date])`
> - `setMonth(month, [date])`
> - `setDate(date)`
> - `setHours(hour, [min], [sec], [ms])`
> - `setMinutes(min, [sec], [ms])`
> - `setSeconds(sec, [ms])`
> - `setMilliseconds(ms)`
> - `setTime(timestamp)` (sets the whole date by milliseconds since 01.01.1970 UTC)
>
> Parameters in `[]` above are _optional_.
> If not mentioned, the components are not modified.
> Every one of them except `setTime()` has a UTC-variant, for instance: `setUTCHours()`. [^6]

```javascript
let today = new Date();

today.setHours(0); // still today, but only the hour is changed to 0

today.setHours(0, 0, 0, 0); // still today, now sharply 00:00:00
```

## Calculating Time Difference and `Date.now()`

To measure the time elapsed between two given dates, we can use the `Date.getTime()` method.

```javascript
const d1 = new Date(2021, 12, 11, 5, 13, 32, 21);
const d2 = new Date(2021, 12, 23, 4, 12, 55);

let timeElapsed = d2.getTime() - d1.getTime(); // => 1033162979
```

Moreover, if we wish to measure the time taken on a live basis, for example the time taken for execution for program, we could use `Date.now()` which provides the timestamp of current time.

## Comparing Dates

We can use `<` and `>` operators to compare two `Date` objects, the date occuring _later being treated as greater_.

The `==` or `===` do not work with `Date`, and output `false` in any case, even if dates are equal.
However, we could use the `Date.getTime()` method to obtain the timestamps (which is of the data type `number`) and compare them using equality operators.

```javascript
const d1 = new Date(2021, 12, 11);
const d2 = new Date(1990, 11, 23);

d1 > d2; // true

const d1Copy = new Date(d1); // d1Copy will be same as d1

d1Copy === d1; // false, even though they are same
d1Copy.getTime() === d1.getTime(); //true
```

[^1]: https://javascript.info/date
[^2]: https://javascript.info/date#setting-date-components
[^3]: https://javascript.info/date#date-parse-from-a-string
[^4]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date#several_ways_to_create_a_date_object
[^5]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/Date#several_ways_to_create_a_date_object
[^6]: https://javascript.info/date#access-date-components

[utc-defn]: https://simple.wikipedia.org/wiki/Coordinated_Universal_Time
[mdn-diff-assumed-timezone]: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse#differences_in_assumed_time_zone
14 changes: 14 additions & 0 deletions exercises/concept/appointment-time/.eslintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
{
"root": true,
"extends": "@exercism/eslint-config-javascript",
"env": {
"jest": true
},
"overrides": [
{
"files": [".meta/proof.ci.js", ".meta/exemplar.js", "*.spec.js"],
"excludedFiles": ["custom.spec.js"],
"extends": "@exercism/eslint-config-javascript/maintainers"
}
]
}
3 changes: 3 additions & 0 deletions exercises/concept/appointment-time/.gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
node_modules
yarn-error.log

23 changes: 23 additions & 0 deletions exercises/concept/appointment-time/.meta/config.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,23 @@
{
"authors": [
"SalahuddinAhammed"
],
"files": {
"solution": [
"appointment-time.js"
],
"test": [
"appointment-time.spec.js"
],
"exemplar": [
".meta/exemplar.js"
]
},
"blurb": "Learn how to work with dates by managing appointments",
"custom": {
"version.tests.compatibility": "jest-29",
"flag.tests.task-per-describe": true,
"flag.tests.may-run-long": false,
"flag.tests.includes-optional": false
}
}
Loading