diff --git a/concepts/temporal-adjusters/.meta/config.json b/concepts/temporal-adjusters/.meta/config.json new file mode 100644 index 000000000..48d931526 --- /dev/null +++ b/concepts/temporal-adjusters/.meta/config.json @@ -0,0 +1,7 @@ +{ + "blurb": "Perform date adjustments using Java's `TemporalAdjuster` interface and `TemporalAdjusters` utility class.", + "authors": [ + "rabestro" + ], + "contributors": [] +} diff --git a/concepts/temporal-adjusters/about.md b/concepts/temporal-adjusters/about.md new file mode 100644 index 000000000..7eb7bc99a --- /dev/null +++ b/concepts/temporal-adjusters/about.md @@ -0,0 +1,140 @@ +# About + +While the core `java.time` classes like `LocalDate` and `LocalDateTime` provide basic methods for adding or subtracting time units, more complex date adjustments often require more sophisticated logic (e.g., finding the "second Tuesday of the month" or the "last day of the year"). + +The `java.time.temporal` package provides the [`TemporalAdjuster`][temporaladjuster-docs] functional interface for this purpose. It represents a strategy for adjusting a temporal object (like a `LocalDate`). The [`TemporalAdjusters`][temporaladjusters-docs] (note the plural 's') utility class contains static factory methods providing many common, predefined adjuster implementations. + +## Using TemporalAdjusters + +Temporal objects like `LocalDate` and `LocalDateTime` have a `with()` method that accepts a `TemporalAdjuster`. This method returns a *new* temporal object with the adjustment applied. + +```exercism/note +Using `with(TemporalAdjuster)` returns a _new_ instance and does not update the existing instance, as all `java.time` temporal classes are immutable. +``` + +```java +import java.time.LocalDate; +import java.time.Month; +import java.time.DayOfWeek; +import java.time.temporal.TemporalAdjusters; + +LocalDate date = LocalDate.of(2024, Month.AUGUST, 15); // 2024-08-15 (a Thursday) + +// Use a predefined adjuster from TemporalAdjusters +LocalDate firstDayOfNextMonth = date.with(TemporalAdjusters.firstDayOfNextMonth()); +// => 2024-09-01 + +LocalDate nextSunday = date.with(TemporalAdjusters.next(DayOfWeek.SUNDAY)); +// => 2024-08-18 +``` + +## Common Predefined Adjusters + +The `TemporalAdjusters` class provides many useful static methods. Here are some common examples: + +### Finding Ordinal Day of Week + +The `dayOfWeekInMonth(int ordinal, DayOfWeek dayOfWeek)` adjuster finds the nth occurrence of a specific day of the week within the month. + +```java +LocalDate date = LocalDate.of(2024, Month.AUGUST, 15); // 2024-08-15 + +// Find the second Tuesday of August 2024 +LocalDate secondTuesday = date.with(TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.TUESDAY)); +// => 2024-08-13 + +// Find the fourth Friday of August 2024 +LocalDate fourthFriday = date.with(TemporalAdjusters.dayOfWeekInMonth(4, DayOfWeek.FRIDAY)); +// => 2024-08-23 +``` + +### Finding First/Last Day of Week in Month + +The `firstInMonth(DayOfWeek dayOfWeek)` and `lastInMonth(DayOfWeek dayOfWeek)` adjusters find the first or last occurrence of a day of the week within the month. + +```java +LocalDate date = LocalDate.of(2024, Month.AUGUST, 15); // 2024-08-15 + +// Find the first Sunday of August 2024 +LocalDate firstSunday = date.with(TemporalAdjusters.firstInMonth(DayOfWeek.SUNDAY)); +// => 2024-08-04 + +// Find the last Monday of August 2024 +LocalDate lastMonday = date.with(TemporalAdjusters.lastInMonth(DayOfWeek.MONDAY)); +// => 2024-08-26 +``` + +### Finding First/Last Day of Month/Year + +Simpler adjusters find the first or last day of the current month or year. + +```java +LocalDate date = LocalDate.of(2024, Month.AUGUST, 15); // 2024-08-15 + +LocalDate firstDay = date.with(TemporalAdjusters.firstDayOfMonth()); +// => 2024-08-01 + +LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth()); +// => 2024-08-31 + +LocalDate lastDayOfYear = date.with(TemporalAdjusters.lastDayOfYear()); +// => 2024-12-31 +``` + +### Relative Adjustments (Next/Previous) + +Adjusters like `next()`, `previous()`, `nextOrSame()`, and `previousOrSame()` find the next or previous occurrence of a given day of the week, relative to the current date. + +- `next()`/`previous()`: Excludes the current date if it matches. +- `nextOrSame()`/`previousOrSame()`: Includes the current date if it matches. + +```java +LocalDate thursday = LocalDate.of(2024, Month.AUGUST, 15); // A Thursday + +// Find the next Sunday (exclusive) +LocalDate nextSunday = thursday.with(TemporalAdjusters.next(DayOfWeek.SUNDAY)); +// => 2024-08-18 + +// Find the next Thursday (exclusive) +LocalDate nextThursday = thursday.with(TemporalAdjusters.next(DayOfWeek.THURSDAY)); +// => 2024-08-22 + +// Find the next Thursday (inclusive) - returns the same date +LocalDate nextOrSameThursday = thursday.with(TemporalAdjusters.nextOrSame(DayOfWeek.THURSDAY)); +// => 2024-08-15 + +// Find the previous Monday (exclusive) +LocalDate previousMonday = thursday.with(TemporalAdjusters.previous(DayOfWeek.MONDAY)); +// => 2024-08-12 +``` + +The `nextOrSame()` adjuster is particularly useful for finding dates in ranges like the "teenth" days (13th-19th) of a month, as seen in the Meetup exercise. Applying `nextOrSame(targetDayOfWeek)` to the 13th day of the month will find the correct "teenth" date. + +## Custom Adjusters + +Since `TemporalAdjuster` is a [`@FunctionalInterface`][functionalinterface-docs], you can create your own custom adjusters using lambda expressions for logic not covered by the predefined methods. The interface requires implementing a single method: `Temporal adjustInto(Temporal temporal)`. + +```java +// Example: An adjuster that finds the next workday (Mon-Fri), skipping weekends. +TemporalAdjuster nextWorkday = temporal -> { + LocalDate result = (LocalDate) temporal; // Assuming input is LocalDate + do { + result = result.plusDays(1); + } while (result.getDayOfWeek() == DayOfWeek.SATURDAY || result.getDayOfWeek() == DayOfWeek.SUNDAY); + return result; +}; + +LocalDate friday = LocalDate.of(2024, Month.AUGUST, 16); +LocalDate nextWorkdayDate = friday.with(nextWorkday); +// => 2024-08-19 (Monday) + +LocalDate sunday = LocalDate.of(2024, Month.AUGUST, 18); +LocalDate nextWorkdayFromSunday = sunday.with(nextWorkday); +// => 2024-08-19 (Monday) +``` + +While custom adjusters are powerful, the predefined adjusters in the `TemporalAdjusters` class cover a wide range of common use cases. + +[temporaladjuster-docs]: https://docs.oracle.com/javase/8/docs/api/java/time/temporal/TemporalAdjuster.html +[temporaladjusters-docs]: https://docs.oracle.com/javase/8/docs/api/java/time/temporal/TemporalAdjusters.html +[functionalinterface-docs]: https://docs.oracle.com/javase/8/docs/api/java/lang/FunctionalInterface.html diff --git a/concepts/temporal-adjusters/introduction.md b/concepts/temporal-adjusters/introduction.md new file mode 100644 index 000000000..d2c6e4ce5 --- /dev/null +++ b/concepts/temporal-adjusters/introduction.md @@ -0,0 +1,62 @@ +# Introduction + +When working with `java.time` objects like `LocalDate`, you often need to perform complex date adjustments, such as finding the "second Tuesday of the month". Instead of calculating this manually, you can use **`TemporalAdjusters`**. + +The `java.time.temporal.TemporalAdjusters` (note the plural 's') utility class provides static methods for many common date adjustments. You apply these adjustments using the `.with()` method on a temporal object (like `LocalDate`). + +```exercism/note +Using `with(TemporalAdjuster)` returns a _new_ instance and does not update the existing instance, as `java.time` objects are immutable. +``` + +```java +import java.time.LocalDate; +import java.time.Month; +import java.time.DayOfWeek; +import java.time.temporal.TemporalAdjusters; + +LocalDate date = LocalDate.of(2024, Month.AUGUST, 15); // 2024-08-15 (a Thursday) + +// Use a predefined adjuster: find the last day of the month +LocalDate lastDay = date.with(TemporalAdjusters.lastDayOfMonth()); +// => 2024-08-31 +``` + +Here are some key adjusters useful for scheduling calculations: + +## Finding Ordinal Day of Week + +Use `dayOfWeekInMonth(int ordinal, DayOfWeek dayOfWeek)` to find the nth occurrence of a day of the week. + +```java +// Find the second Tuesday of August 2024 +LocalDate secondTuesday = date.with(TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.TUESDAY)); +// => 2024-08-13 +``` + +## Finding First/Last Day of Week in Month + +Use `firstInMonth(DayOfWeek dayOfWeek)` or `lastInMonth(DayOfWeek dayOfWeek)`. + +```java +// Find the last Monday of August 2024 +LocalDate lastMonday = date.with(TemporalAdjusters.lastInMonth(DayOfWeek.MONDAY)); +// => 2024-08-26 +``` + +## Finding Relative Occurrences ("Teenth" dates) + +Use `nextOrSame(DayOfWeek dayOfWeek)`. This is useful for finding dates like the "teenth" days (13th-19th). Apply it to the 13th day of the month to find the target day of the week within that "teenth" range. + +```java +LocalDate thirteenth = LocalDate.of(2024, Month.AUGUST, 13); // Tuesday the 13th + +// Find the first Saturday on or after the 13th ("Teenth" Saturday) +LocalDate teenthSaturday = thirteenth.with(TemporalAdjusters.nextOrSame(DayOfWeek.SATURDAY)); +// => 2024-08-17 + +// Find the first Tuesday on or after the 13th ("Teenth" Tuesday) +LocalDate teenthTuesday = thirteenth.with(TemporalAdjusters.nextOrSame(DayOfWeek.TUESDAY)); +// => 2024-08-13 (returns the same date as it matches) +``` + +Using these adjusters from the `TemporalAdjusters` class can greatly simplify date manipulation tasks. diff --git a/concepts/temporal-adjusters/links.json b/concepts/temporal-adjusters/links.json new file mode 100644 index 000000000..d2a0b0185 --- /dev/null +++ b/concepts/temporal-adjusters/links.json @@ -0,0 +1,18 @@ +[ + { + "url": "https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/time/temporal/TemporalAdjuster.html", + "description": "TemporalAdjuster interface documentation" + }, + { + "url": "https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/time/temporal/TemporalAdjusters.html", + "description": "TemporalAdjusters utility class documentation" + }, + { + "url": "https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/time/temporal/Temporal.html", + "description": "Temporal interface documentation" + }, + { + "url": "https://docs.oracle.com/en/java/javase/21/docs/api/java.base/java/time/DayOfWeek.html", + "description": "DayOfWeek enum documentation" + } +] diff --git a/config.json b/config.json index 7c8f6b933..cd9ca7b86 100644 --- a/config.json +++ b/config.json @@ -321,6 +321,18 @@ "foreach-loops", "generic-types" ] + }, + { + "slug": "meetup", + "name": "Meetup", + "uuid": "602511d5-7e89-4def-b072-4dd311816810", + "concepts": [ + "temporal-adjusters" + ], + "prerequisites": [ + "datetime", + "enums" + ] } ], "practice": [ @@ -1481,17 +1493,6 @@ ], "difficulty": 7 }, - { - "slug": "meetup", - "name": "Meetup", - "uuid": "602511d5-7e89-4def-b072-4dd311816810", - "practices": [], - "prerequisites": [ - "datetime", - "enums" - ], - "difficulty": 7 - }, { "slug": "poker", "name": "Poker", @@ -1971,6 +1972,11 @@ "uuid": "78f3c7b2-cb9c-4d21-8cb4-7106a188f713", "slug": "ternary-operators", "name": "Ternary Operators" + }, + { + "uuid": "cc7a06d1-ddb3-4722-88a5-f762254d664e", + "slug": "temporal-adjusters", + "name": "Temporal Adjusters" } ], "key_features": [ diff --git a/exercises/concept/meetup/.docs/hints.md b/exercises/concept/meetup/.docs/hints.md new file mode 100644 index 000000000..8080fee71 --- /dev/null +++ b/exercises/concept/meetup/.docs/hints.md @@ -0,0 +1,43 @@ +# Hints + +## 1. Representing the Date + +- The core class for representing dates without time in Java is [`java.time.LocalDate`][localdate-docs]. +- You'll need to work with the `year` and `month` provided in the constructor. +- The target day of the week is conveniently provided directly as a [`java.time.DayOfWeek`][dayofweek-docs] enum instance in the `day()` method. + +## 2. Starting Point for Adjustments + +- `LocalDate` objects are immutable. To find the target meetup date, you typically start with *any* date within the target `month` and `year` and then apply an "adjuster" to find the correct day. +- For example, you could create a `LocalDate` for the 1st of the month: `LocalDate.of(year, month, 1)`. +- For "Teenth" calculations, starting from the 13th of the month (`LocalDate.of(year, month, 13)`) can be helpful. + +## 3. Adjusting Dates with `TemporalAdjusters` + +- The key to solving this idiomatically is the [`java.time.temporal.TemporalAdjusters`][temporaladjusters-docs] utility class (note the plural 's'). It provides static methods that return [`TemporalAdjuster`][temporaladjuster-docs] instances for common date calculations. +- You apply an adjuster to a `LocalDate` using its `.with()` method: `someLocalDate.with(TemporalAdjusters.someAdjuster(...))` +- This returns a *new* `LocalDate` instance with the adjustment applied. + +## 4. Handling "Ordinal" Schedules (FIRST, SECOND, THIRD, FOURTH) + +- Look for a method in `TemporalAdjusters` that allows you to find a date based on its ordinal position (1st, 2nd, 3rd, 4th) and its `DayOfWeek` within the month. +- You might need to convert the `MeetupSchedule` enum values (`FIRST`, `SECOND`, etc.) into the corresponding integer ordinals (1, 2, 3, 4) to use this adjuster. + +## 5. Handling the "LAST" Schedule + +- `TemporalAdjusters` provides a specific adjuster to find the *last* occurrence of a given `DayOfWeek` within the month. + +## 6. Handling the "TEENTH" Schedule + +- "Teenth" days run from the 13th to the 19th of the month. +- Consider starting from the 13th day of the month (`LocalDate.of(year, month, 13)`). +- Look for an adjuster in `TemporalAdjusters` that finds the *next* occurrence of the target `DayOfWeek`, potentially *including* the date you're adjusting if it already matches the target day of the week. + +## 7. Selecting the Right Adjuster + +- Use the input `schedule` (which is a `MeetupSchedule` enum value) to determine which specific `TemporalAdjuster` method to use. A `switch` statement or `if-else if` chain on the `schedule` value is a common approach. + +[localdate-docs]: https://docs.oracle.com/javase/8/docs/api/java/time/LocalDate.html +[dayofweek-docs]: https://docs.oracle.com/javase/8/docs/api/java/time/DayOfWeek.html +[temporaladjuster-docs]: https://docs.oracle.com/javase/8/docs/api/java/time/temporal/TemporalAdjuster.html +[temporaladjusters-docs]: https://docs.oracle.com/javase/8/docs/api/java/time/temporal/TemporalAdjusters.html diff --git a/exercises/practice/meetup/.docs/instructions.md b/exercises/concept/meetup/.docs/instructions.md similarity index 100% rename from exercises/practice/meetup/.docs/instructions.md rename to exercises/concept/meetup/.docs/instructions.md diff --git a/exercises/practice/meetup/.docs/introduction.md b/exercises/concept/meetup/.docs/introduction.md similarity index 100% rename from exercises/practice/meetup/.docs/introduction.md rename to exercises/concept/meetup/.docs/introduction.md diff --git a/exercises/concept/meetup/.docs/introduction.md.tpl b/exercises/concept/meetup/.docs/introduction.md.tpl new file mode 100644 index 000000000..1dc0a9066 --- /dev/null +++ b/exercises/concept/meetup/.docs/introduction.md.tpl @@ -0,0 +1,3 @@ +# Introduction + +%{concept:strings} diff --git a/exercises/practice/meetup/.meta/config.json b/exercises/concept/meetup/.meta/config.json similarity index 97% rename from exercises/practice/meetup/.meta/config.json rename to exercises/concept/meetup/.meta/config.json index f312b8205..44da62752 100644 --- a/exercises/practice/meetup/.meta/config.json +++ b/exercises/concept/meetup/.meta/config.json @@ -30,7 +30,7 @@ "test": [ "src/test/java/MeetupTest.java" ], - "example": [ + "exemplar": [ ".meta/src/reference/java/Meetup.java" ], "editor": [ diff --git a/exercises/concept/meetup/.meta/design.md b/exercises/concept/meetup/.meta/design.md new file mode 100644 index 000000000..81faaa66b --- /dev/null +++ b/exercises/concept/meetup/.meta/design.md @@ -0,0 +1,45 @@ +# Design + +## Learning objectives + +- Know about the `java.time.temporal.TemporalAdjuster` interface and its purpose. +- Know about the `java.time.temporal.TemporalAdjusters` utility class and how to use its static factory methods. +- Know how to apply a `TemporalAdjuster` to a `LocalDate` using the `.with()` method. +- Know how to select and use common predefined adjusters like `TemporalAdjusters.dayOfWeekInMonth()`, `TemporalAdjusters.lastInMonth()`, and `TemporalAdjusters.nextOrSame()`. +- Understand that `java.time` objects are immutable and adjustment methods return new instances. +- Know how to use a `java.time.DayOfWeek` enum value. +- Know how to use a custom `enum` (like `MeetupSchedule`) in conditional logic (e.g., `switch` statement). + +## Out of scope + +- Creating complex custom `TemporalAdjuster` implementations. +- Time zones, offsets, `ZonedDateTime`. +- `LocalDateTime`, `LocalTime`. +- Durations (`java.time.Duration`) and Periods (`java.time.Period`). +- Date/time parsing and formatting. + +## Concepts + +- `temporal-adjusters`: This exercise introduces and focuses on the `TemporalAdjusters` concept. +- `datetime`: Reinforces basic usage of `LocalDate` and `DayOfWeek`. +- `enums`: Reinforces usage of enums. + +## Prerequisites + +- `datetime`: Must know how to create and use basic `java.time.LocalDate` objects and understand `DayOfWeek`. +- `enums`: Must know how to work with `enum` types, including using them in `switch` statements or accessing properties like `ordinal()`. +- `classes`: Basic understanding of Java classes and methods. +- `methods`: Basic understanding of Java methods. + +## Analyzer + +This exercise could benefit from the following rules in the [analyzer]: + +- `essential` (replaces `actionable` if it MUST be fixed): If the solution involves significant manual date calculation logic (e.g., loops checking day of week, complex `plusDays`/`minusDays` sequences) instead of using `TemporalAdjusters`, instruct the student that using the `TemporalAdjusters` class is the idiomatic approach for this exercise. Provide a link to the `TemporalAdjusters` concept documentation. +- `actionable`: If the student uses `TemporalAdjusters.dayOfWeekInMonth()`, check if they correctly map the `MeetupSchedule` enum ordinal (0-based) to the required 1-based ordinal argument. If not, provide a hint. +- `actionable`: If the logic for `MeetupSchedule.TEENTH` seems incorrect or overly complex, suggest using `TemporalAdjusters.nextOrSame()` applied to the 13th day of the month. +- `informative`: If the student uses `TemporalAdjusters` correctly, mention the specific adjusters used (`dayOfWeekInMonth`, `lastInMonth`, `nextOrSame`) as good choices for their respective cases. + +If the solution uses `TemporalAdjusters` correctly for all `MeetupSchedule` cases, it should be considered exemplar. Leave a `celebratory` comment to celebrate the success! + +[analyzer]: https://github.com/exercism/java-analyzer diff --git a/exercises/practice/meetup/.meta/src/reference/java/Meetup.java b/exercises/concept/meetup/.meta/src/reference/java/Meetup.java similarity index 100% rename from exercises/practice/meetup/.meta/src/reference/java/Meetup.java rename to exercises/concept/meetup/.meta/src/reference/java/Meetup.java diff --git a/exercises/practice/meetup/.meta/src/reference/java/MeetupSchedule.java b/exercises/concept/meetup/.meta/src/reference/java/MeetupSchedule.java similarity index 100% rename from exercises/practice/meetup/.meta/src/reference/java/MeetupSchedule.java rename to exercises/concept/meetup/.meta/src/reference/java/MeetupSchedule.java diff --git a/exercises/practice/meetup/build.gradle b/exercises/concept/meetup/build.gradle similarity index 100% rename from exercises/practice/meetup/build.gradle rename to exercises/concept/meetup/build.gradle diff --git a/exercises/practice/meetup/gradle/wrapper/gradle-wrapper.jar b/exercises/concept/meetup/gradle/wrapper/gradle-wrapper.jar similarity index 100% rename from exercises/practice/meetup/gradle/wrapper/gradle-wrapper.jar rename to exercises/concept/meetup/gradle/wrapper/gradle-wrapper.jar diff --git a/exercises/practice/meetup/gradle/wrapper/gradle-wrapper.properties b/exercises/concept/meetup/gradle/wrapper/gradle-wrapper.properties similarity index 100% rename from exercises/practice/meetup/gradle/wrapper/gradle-wrapper.properties rename to exercises/concept/meetup/gradle/wrapper/gradle-wrapper.properties diff --git a/exercises/practice/meetup/gradlew b/exercises/concept/meetup/gradlew similarity index 100% rename from exercises/practice/meetup/gradlew rename to exercises/concept/meetup/gradlew diff --git a/exercises/practice/meetup/gradlew.bat b/exercises/concept/meetup/gradlew.bat similarity index 100% rename from exercises/practice/meetup/gradlew.bat rename to exercises/concept/meetup/gradlew.bat diff --git a/exercises/practice/meetup/src/main/java/Meetup.java b/exercises/concept/meetup/src/main/java/Meetup.java similarity index 100% rename from exercises/practice/meetup/src/main/java/Meetup.java rename to exercises/concept/meetup/src/main/java/Meetup.java diff --git a/exercises/practice/meetup/src/main/java/MeetupSchedule.java b/exercises/concept/meetup/src/main/java/MeetupSchedule.java similarity index 100% rename from exercises/practice/meetup/src/main/java/MeetupSchedule.java rename to exercises/concept/meetup/src/main/java/MeetupSchedule.java diff --git a/exercises/practice/meetup/src/test/java/MeetupTest.java b/exercises/concept/meetup/src/test/java/MeetupTest.java similarity index 100% rename from exercises/practice/meetup/src/test/java/MeetupTest.java rename to exercises/concept/meetup/src/test/java/MeetupTest.java diff --git a/exercises/practice/meetup/.meta/tests.toml b/exercises/practice/meetup/.meta/tests.toml deleted file mode 100644 index 76a8e06ae..000000000 --- a/exercises/practice/meetup/.meta/tests.toml +++ /dev/null @@ -1,288 +0,0 @@ -# This is an auto-generated file. Regular comments will be removed when this -# file is regenerated. Regenerating will not touch any manually added keys, -# so comments can be added in a "comment" key. - -[d7f8eadd-d4fc-46ee-8a20-e97bd3fd01c8] -description = "monteenth of May 2013" - -[f78373d1-cd53-4a7f-9d37-e15bf8a456b4] -description = "monteenth of August 2013" - -[8c78bea7-a116-425b-9c6b-c9898266d92a] -description = "monteenth of September 2013" - -[cfef881b-9dc9-4d0b-8de4-82d0f39fc271] -description = "tuesteenth of March 2013" - -[69048961-3b00-41f9-97ee-eb6d83a8e92b] -description = "tuesteenth of April 2013" - -[d30bade8-3622-466a-b7be-587414e0caa6] -description = "tuesteenth of August 2013" - -[8db4b58b-92f3-4687-867b-82ee1a04f851] -description = "wednesteenth of January 2013" - -[6c27a2a2-28f8-487f-ae81-35d08c4664f7] -description = "wednesteenth of February 2013" - -[008a8674-1958-45b5-b8e6-c2c9960d973a] -description = "wednesteenth of June 2013" - -[e4abd5e3-57cb-4091-8420-d97e955c0dbd] -description = "thursteenth of May 2013" - -[85da0b0f-eace-4297-a6dd-63588d5055b4] -description = "thursteenth of June 2013" - -[ecf64f9b-8413-489b-bf6e-128045f70bcc] -description = "thursteenth of September 2013" - -[ac4e180c-7d0a-4d3d-b05f-f564ebb584ca] -description = "friteenth of April 2013" - -[b79101c7-83ad-4f8f-8ec8-591683296315] -description = "friteenth of August 2013" - -[6ed38b9f-0072-4901-bd97-7c8b8b0ef1b8] -description = "friteenth of September 2013" - -[dfae03ed-9610-47de-a632-655ab01e1e7c] -description = "saturteenth of February 2013" - -[ec02e3e1-fc72-4a3c-872f-a53fa8ab358e] -description = "saturteenth of April 2013" - -[d983094b-7259-4195-b84e-5d09578c89d9] -description = "saturteenth of October 2013" - -[d84a2a2e-f745-443a-9368-30051be60c2e] -description = "sunteenth of May 2013" - -[0e64bc53-92a3-4f61-85b2-0b7168c7ce5a] -description = "sunteenth of June 2013" - -[de87652c-185e-4854-b3ae-04cf6150eead] -description = "sunteenth of October 2013" - -[2cbfd0f5-ba3a-46da-a8cc-0fe4966d3411] -description = "first Monday of March 2013" - -[a6168c7c-ed95-4bb3-8f92-c72575fc64b0] -description = "first Monday of April 2013" - -[1bfc620f-1c54-4bbd-931f-4a1cd1036c20] -description = "first Tuesday of May 2013" - -[12959c10-7362-4ca0-a048-50cf1c06e3e2] -description = "first Tuesday of June 2013" - -[1033dc66-8d0b-48a1-90cb-270703d59d1d] -description = "first Wednesday of July 2013" - -[b89185b9-2f32-46f4-a602-de20b09058f6] -description = "first Wednesday of August 2013" - -[53aedc4d-b2c8-4dfb-abf7-a8dc9cdceed5] -description = "first Thursday of September 2013" - -[b420a7e3-a94c-4226-870a-9eb3a92647f0] -description = "first Thursday of October 2013" - -[61df3270-28b4-4713-bee2-566fa27302ca] -description = "first Friday of November 2013" - -[cad33d4d-595c-412f-85cf-3874c6e07abf] -description = "first Friday of December 2013" - -[a2869b52-5bba-44f0-a863-07bd1f67eadb] -description = "first Saturday of January 2013" - -[3585315a-d0db-4ea1-822e-0f22e2a645f5] -description = "first Saturday of February 2013" - -[c49e9bd9-8ccf-4cf2-947a-0ccd4e4f10b1] -description = "first Sunday of March 2013" - -[1513328b-df53-4714-8677-df68c4f9366c] -description = "first Sunday of April 2013" - -[49e083af-47ec-4018-b807-62ef411efed7] -description = "second Monday of March 2013" - -[6cb79a73-38fe-4475-9101-9eec36cf79e5] -description = "second Monday of April 2013" - -[4c39b594-af7e-4445-aa03-bf4f8effd9a1] -description = "second Tuesday of May 2013" - -[41b32c34-2e39-40e3-b790-93539aaeb6dd] -description = "second Tuesday of June 2013" - -[90a160c5-b5d9-4831-927f-63a78b17843d] -description = "second Wednesday of July 2013" - -[23b98ce7-8dd5-41a1-9310-ef27209741cb] -description = "second Wednesday of August 2013" - -[447f1960-27ca-4729-bc3f-f36043f43ed0] -description = "second Thursday of September 2013" - -[c9aa2687-300c-4e79-86ca-077849a81bde] -description = "second Thursday of October 2013" - -[a7e11ef3-6625-4134-acda-3e7195421c09] -description = "second Friday of November 2013" - -[8b420e5f-9290-4106-b5ae-022f3e2a3e41] -description = "second Friday of December 2013" - -[80631afc-fc11-4546-8b5f-c12aaeb72b4f] -description = "second Saturday of January 2013" - -[e34d43ac-f470-44c2-aa5f-e97b78ecaf83] -description = "second Saturday of February 2013" - -[a57d59fd-1023-47ad-b0df-a6feb21b44fc] -description = "second Sunday of March 2013" - -[a829a8b0-abdd-4ad1-b66c-5560d843c91a] -description = "second Sunday of April 2013" - -[501a8a77-6038-4fc0-b74c-33634906c29d] -description = "third Monday of March 2013" - -[49e4516e-cf32-4a58-8bbc-494b7e851c92] -description = "third Monday of April 2013" - -[4db61095-f7c7-493c-85f1-9996ad3012c7] -description = "third Tuesday of May 2013" - -[714fc2e3-58d0-4b91-90fd-61eefd2892c0] -description = "third Tuesday of June 2013" - -[b08a051a-2c80-445b-9b0e-524171a166d1] -description = "third Wednesday of July 2013" - -[80bb9eff-3905-4c61-8dc9-bb03016d8ff8] -description = "third Wednesday of August 2013" - -[fa52a299-f77f-4784-b290-ba9189fbd9c9] -description = "third Thursday of September 2013" - -[f74b1bc6-cc5c-4bf1-ba69-c554a969eb38] -description = "third Thursday of October 2013" - -[8900f3b0-801a-466b-a866-f42d64667abd] -description = "third Friday of November 2013" - -[538ac405-a091-4314-9ccd-920c4e38e85e] -description = "third Friday of December 2013" - -[244db35c-2716-4fa0-88ce-afd58e5cf910] -description = "third Saturday of January 2013" - -[dd28544f-f8fa-4f06-9bcd-0ad46ce68e9e] -description = "third Saturday of February 2013" - -[be71dcc6-00d2-4b53-a369-cbfae55b312f] -description = "third Sunday of March 2013" - -[b7d2da84-4290-4ee6-a618-ee124ae78be7] -description = "third Sunday of April 2013" - -[4276dc06-a1bd-4fc2-b6c2-625fee90bc88] -description = "fourth Monday of March 2013" - -[ddbd7976-2deb-4250-8a38-925ac1a8e9a2] -description = "fourth Monday of April 2013" - -[eb714ef4-1656-47cc-913c-844dba4ebddd] -description = "fourth Tuesday of May 2013" - -[16648435-7937-4d2d-b118-c3e38fd084bd] -description = "fourth Tuesday of June 2013" - -[de062bdc-9484-437a-a8c5-5253c6f6785a] -description = "fourth Wednesday of July 2013" - -[c2ce6821-169c-4832-8d37-690ef5d9514a] -description = "fourth Wednesday of August 2013" - -[d462c631-2894-4391-a8e3-dbb98b7a7303] -description = "fourth Thursday of September 2013" - -[9ff1f7b6-1b72-427d-9ee9-82b5bb08b835] -description = "fourth Thursday of October 2013" - -[83bae8ba-1c49-49bc-b632-b7c7e1d7e35f] -description = "fourth Friday of November 2013" - -[de752d2a-a95e-48d2-835b-93363dac3710] -description = "fourth Friday of December 2013" - -[eedd90ad-d581-45db-8312-4c6dcf9cf560] -description = "fourth Saturday of January 2013" - -[669fedcd-912e-48c7-a0a1-228b34af91d0] -description = "fourth Saturday of February 2013" - -[648e3849-ea49-44a5-a8a3-9f2a43b3bf1b] -description = "fourth Sunday of March 2013" - -[f81321b3-99ab-4db6-9267-69c5da5a7823] -description = "fourth Sunday of April 2013" - -[1af5e51f-5488-4548-aee8-11d7d4a730dc] -description = "last Monday of March 2013" - -[f29999f2-235e-4ec7-9dab-26f137146526] -description = "last Monday of April 2013" - -[31b097a0-508e-48ac-bf8a-f63cdcf6dc41] -description = "last Tuesday of May 2013" - -[8c022150-0bb5-4a1f-80f9-88b2e2abcba4] -description = "last Tuesday of June 2013" - -[0e762194-672a-4bdf-8a37-1e59fdacef12] -description = "last Wednesday of July 2013" - -[5016386a-f24e-4bd7-b439-95358f491b66] -description = "last Wednesday of August 2013" - -[12ead1a5-cdf9-4192-9a56-2229e93dd149] -description = "last Thursday of September 2013" - -[7db89e11-7fbe-4e57-ae3c-0f327fbd7cc7] -description = "last Thursday of October 2013" - -[e47a739e-b979-460d-9c8a-75c35ca2290b] -description = "last Friday of November 2013" - -[5bed5aa9-a57a-4e5d-8997-2cc796a5b0ec] -description = "last Friday of December 2013" - -[61e54cba-76f3-4772-a2b1-bf443fda2137] -description = "last Saturday of January 2013" - -[8b6a737b-2fa9-444c-b1a2-80ce7a2ec72f] -description = "last Saturday of February 2013" - -[0b63e682-f429-4d19-9809-4a45bd0242dc] -description = "last Sunday of March 2013" - -[5232307e-d3e3-4afc-8ba6-4084ad987c00] -description = "last Sunday of April 2013" - -[0bbd48e8-9773-4e81-8e71-b9a51711e3c5] -description = "last Wednesday of February 2012" - -[fe0936de-7eee-4a48-88dd-66c07ab1fefc] -description = "last Wednesday of December 2014" - -[2ccf2488-aafc-4671-a24e-2b6effe1b0e2] -description = "last Sunday of February 2015" - -[00c3ce9f-cf36-4b70-90d8-92b32be6830e] -description = "first Friday of December 2012" diff --git a/exercises/settings.gradle b/exercises/settings.gradle index 2ff1e9a14..8dc7dc723 100644 --- a/exercises/settings.gradle +++ b/exercises/settings.gradle @@ -16,6 +16,7 @@ include 'concept:karls-languages' include 'concept:lasagna' include 'concept:log-levels' include 'concept:logs-logs-logs' +include 'concept:meetup' include 'concept:need-for-speed' include 'concept:remote-control-competition' include 'concept:salary-calculator' @@ -91,7 +92,6 @@ include 'practice:markdown' include 'practice:matching-brackets' include 'practice:matrix' include 'practice:mazy-mice' -include 'practice:meetup' include 'practice:micro-blog' include 'practice:minesweeper' include 'practice:nth-prime'