Διαδρομές
/
Java
Java
/
Ασκήσεις
/
Τακτικοί πελάτες κομμωτηρίου
Τακτικοί πελάτες κομμωτηρίου

Τακτικοί πελάτες κομμωτηρίου

Άσκηση εκμάθησης

Εισαγωγή

Temporal Adjusters

Όταν δουλεύεις με αντικείμενα java.time όπως το LocalDate, συχνά χρειάζεται να κάνεις σύνθετες προσαρμογές ημερομηνιών, όπως να βρεις "τη δεύτερη Τρίτη του μήνα". Αντί να το υπολογίσεις αυτό με το χέρι, μπορείς να χρησιμοποιήσεις τους TemporalAdjusters.

Η βοηθητική κλάση java.time.temporal.TemporalAdjusters (προσέξτε το πληθυντικό 's') παρέχει στατικές μεθόδους για πολλές συνηθισμένες προσαρμογές ημερομηνιών. Εφαρμόζεις αυτές τις προσαρμογές με τη μέθοδο .with() πάνω σε ένα αντικείμενο χρόνου (όπως το LocalDate).

Note

Η χρήση του with(TemporalAdjuster) επιστρέφει ένα νέο παράδειγμα και δεν ενημερώνει το υπάρχον, καθώς τα αντικείμενα java.time είναι αμετάβλητα.

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

Ακολουθούν μερικοί βασικοί προσαρμοστές που βοηθούν σε υπολογισμούς προγράμματος:

Εύρεση της n-οστής ημέρας της εβδομάδας

Χρησιμοποίησε την dayOfWeekInMonth(int ordinal, DayOfWeek dayOfWeek) για να βρεις την n-οστή εμφάνιση μιας ημέρας της εβδομάδας.

// Find the second Tuesday of August 2024
LocalDate secondTuesday = date.with(TemporalAdjusters.dayOfWeekInMonth(2, DayOfWeek.TUESDAY));
// => 2024-08-13

Εύρεση της πρώτης/τελευταίας εμφάνισης μιας ημέρας της εβδομάδας στον μήνα

Χρησιμοποίησε την firstInMonth(DayOfWeek dayOfWeek) ή την lastInMonth(DayOfWeek dayOfWeek).

// Find the last Monday of August 2024
LocalDate lastMonday = date.with(TemporalAdjusters.lastInMonth(DayOfWeek.MONDAY));
// => 2024-08-26

Σχετικές προσαρμογές (επόμενη/προηγούμενη)

Προσαρμοστές όπως οι next(), previous(), nextOrSame() και previousOrSame() βρίσκουν την επόμενη ή την προηγούμενη εμφάνιση μιας δεδομένης ημέρας της εβδομάδας, σε σχέση με την τρέχουσα ημερομηνία.

  • next()/previous(): Εξαιρούν την τρέχουσα ημερομηνία αν ταιριάζει.
  • nextOrSame()/previousOrSame(): Περιλαμβάνουν την τρέχουσα ημερομηνία αν ταιριάζει.
LocalDate thursday = LocalDate.of(2024, Month.AUGUST, 15); // A Thursday

// 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

Δικοί σου προσαρμοστές

Το TemporalAdjuster είναι μια λειτουργική διεπαφή, οπότε μπορείς να γράψεις τον δικό σου προσαρμοστή ως λάμδα που παίρνει το χρονικό αντικείμενο προς προσαρμογή και επιστρέφει το προσαρμοσμένο. Εφαρμόζεται με .with() ακριβώς όπως οι προκαθορισμένοι προσαρμοστές και μπορεί να τους χρησιμοποιεί εσωτερικά.

import java.time.temporal.TemporalAdjuster;

// An adjuster that moves a weekend date to the following Monday
TemporalAdjuster skipWeekend = temporal -> {
    DayOfWeek day = DayOfWeek.from(temporal);
    if (day == DayOfWeek.SATURDAY || day == DayOfWeek.SUNDAY) {
        return temporal.with(TemporalAdjusters.next(DayOfWeek.MONDAY));
    }
    return temporal;
};

LocalDate saturday = LocalDate.of(2024, Month.AUGUST, 17);
LocalDate monday = saturday.with(skipWeekend);
// => 2024-08-19

Η χρήση αυτών των προσαρμοστών από την κλάση TemporalAdjusters μπορεί να απλοποιήσει πολύ τις εργασίες χειρισμού ημερομηνιών.

Οδηγίες

Το κομμωτήριο στη Νέα Υόρκη που βοήθησες στην άσκηση Booking Up For Beauty τα πάει καλά, και πολλοί από τους πελάτες του έχουν γίνει τακτικοί. Αντί να κλείνει κάθε επίσκεψη ξεχωριστά, ένας τακτικός πελάτης έχει μια πάγια συμφωνία: "κάθε δεύτερη Τρίτη", "την τελευταία Παρασκευή του μήνα" και τα λοιπά. Ο ιδιοκτήτης του κομμωτηρίου σού ζήτησε ένα βοηθητικό εργαλείο που υπολογίζει τις ημερομηνίες πίσω από αυτές τις συμφωνίες, καθώς και τις ημερομηνίες της μηνιαίας ρουτίνας του κομμωτηρίου.

1. Βρες το πάγιο ραντεβού ενός τακτικού πελάτη

Υλοποίησε τη μέθοδο SalonCalendar.standingAppointment() που δέχεται ένα έτος, έναν μήνα, μια εμφάνιση (1 για την πρώτη, 2 για τη δεύτερη κ.ο.κ.) και μια ημέρα της εβδομάδας. Επιστρέφει την ημερομηνία εκείνης της εμφάνισης της ημέρας της εβδομάδας μέσα στον μήνα:

SalonCalendar calendar = new SalonCalendar();
calendar.standingAppointment(2024, Month.AUGUST, 2, DayOfWeek.TUESDAY);
// => LocalDate.of(2024, 8, 13)

2. Βρες το ραντεβού τέλους του μήνα ενός τακτικού πελάτη

Μερικοί τακτικοί πελάτες προτιμούν την τελευταία εμφάνιση της ημέρας τους μέσα στον μήνα. Υλοποίησε τη μέθοδο SalonCalendar.lastAppointment() που δέχεται ένα έτος, έναν μήνα και μια ημέρα της εβδομάδας, και επιστρέφει την ημερομηνία της τελευταίας εμφάνισης εκείνης της ημέρας της εβδομάδας μέσα στον μήνα:

SalonCalendar calendar = new SalonCalendar();
calendar.lastAppointment(2024, Month.AUGUST, DayOfWeek.FRIDAY);
// => LocalDate.of(2024, 8, 30)

3. Βρες την επόμενη διαθέσιμη ημέρα για έναν πελάτη χωρίς ραντεβού

Ένας πελάτης στη ρεσεψιόν ζητά "το επόμενο Σάββατο". Αν η μέρα κατά την οποία ρωτά είναι ήδη Σάββατο, εννοεί αυτό το ίδιο το Σάββατο. Υλοποίησε τη μέθοδο SalonCalendar.nextAvailable() που δέχεται μια ημερομηνία και μια ημέρα της εβδομάδας, και επιστρέφει την πρώτη ημερομηνία από τη δεδομένη ημερομηνία και μετά που πέφτει σε εκείνη την ημέρα της εβδομάδας:

SalonCalendar calendar = new SalonCalendar();
calendar.nextAvailable(LocalDate.of(2024, 8, 15), DayOfWeek.SATURDAY);
// => LocalDate.of(2024, 8, 17)
calendar.nextAvailable(LocalDate.of(2024, 8, 17), DayOfWeek.SATURDAY);
// => LocalDate.of(2024, 8, 17)

4. Βρες την ημέρα κλεισίματος των βιβλίων

Το κομμωτήριο κλείνει τα βιβλία του την τελευταία μέρα κάθε μήνα. Ωστόσο, το κομμωτήριο είναι κλειστό τα Σαββατοκύριακα, οπότε όταν η τελευταία μέρα του μήνα πέφτει Σάββατο ή Κυριακή, τα βιβλία κλείνουν την Παρασκευή που προηγείται. Υλοποίησε τη μέθοδο SalonCalendar.bookkeepingDay() που δέχεται ένα έτος και έναν μήνα, και επιστρέφει την ημέρα κλεισίματος των βιβλίων εκείνου του μήνα:

SalonCalendar calendar = new SalonCalendar();
calendar.bookkeepingDay(2024, Month.SEPTEMBER);
// => LocalDate.of(2024, 9, 30)
calendar.bookkeepingDay(2024, Month.AUGUST);
// => LocalDate.of(2024, 8, 30)

5. Χρησιμοποίησε ξανά τον κανόνα του Σαββατοκύριακου για τη μέρα πληρωμής

Το προσωπικό πληρώνεται στις 15 κάθε μήνα, με τον ίδιο κανόνα του Σαββατοκύριακου: όταν η 15η πέφτει Σάββατο ή Κυριακή, η μέρα πληρωμής είναι η Παρασκευή που προηγείται. Αντί να γράψεις τον κανόνα για δεύτερη φορά, μετέτρεψέ τον σε έναν προσαρμοστή που μπορείς να επαναχρησιμοποιήσεις.

Υλοποίησε τη μέθοδο SalonCalendar.precedingWorkday() που επιστρέφει έναν TemporalAdjuster, ο οποίος αφήνει μια εργάσιμη μέρα αμετάβλητη και μετακινεί ένα Σάββατο ή μια Κυριακή στην Παρασκευή που προηγείται. Στη συνέχεια υλοποίησε τη μέθοδο SalonCalendar.payday(), που δέχεται ένα έτος και έναν μήνα, χρησιμοποιώντας αυτόν τον προσαρμοστή:

SalonCalendar calendar = new SalonCalendar();
LocalDate.of(2024, 6, 15).with(calendar.precedingWorkday());
// => LocalDate.of(2024, 6, 14)
calendar.payday(2024, Month.JUNE);
// => LocalDate.of(2024, 6, 14)
calendar.payday(2024, Month.AUGUST);
// => LocalDate.of(2024, 8, 15)

Μη διστάσεις να γυρίσεις πίσω και να χρησιμοποιήσεις τον προσαρμοστή και στη bookkeepingDay().

Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα
Java Exercism

Έτοιμος να ξεκινήσεις την άσκηση Τακτικοί πελάτες κομμωτηρίου;

Γράψου στο Exercism για να μάθεις και να κατακτήσεις Java με 27 έννοιες159 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.