Ώρα Ραντεβού

Ώρα Ραντεβού

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

Εισαγωγή

Η JavaScript έχει ένα ενσωματωμένο αντικείμενο, το Date, το οποίο αποθηκεύει ημερομηνία και ώρα και παρέχει μεθόδους για τη διαχείρισή τους.

Caution

Βασίστηκε στην κλάση java.util.Date της Java, η οποία αντικαταστάθηκε στις αρχές της δεκαετίας του 2010, αλλά για λόγους συμβατότητας προς τα πίσω, το Date της JavaScript παραμένει.

Επειδή είναι γενικά δύσκολο να δουλέψεις με ημερομηνίες και επειδή ο χειρισμός των ζωνών ώρας είναι κακός ή ανύπαρκτος, υπάρχουν πολλές βιβλιοθήκες, όπως οι moment.js, day.js, date-fns και luxon. Καμία από αυτές δεν είναι διαθέσιμη στο Exercism.

Στα δικά σου έργα, μη χρησιμοποιείς ένα πακέτο που έχει καταργηθεί ή δε συντηρείται, όπως το moment.js, αλλά βασίσου σε πιο σύγχρονες εναλλακτικές, όπως το luxon, ή στο Temporal, που δεν είναι ακόμη ευρέως διαθέσιμο. Αυτή η άσκηση εστιάζει στο Date, το οποίο θα παραμείνει σχετικό μέχρι το τέλος της JavaScript.

Δημιουργία

Ένα αντικείμενο Date είναι ένα στιγμιότυπο της κλάσης Date. Μπορεί να δημιουργηθεί χωρίς να περάσεις κανένα όρισμα στη συνάρτηση κατασκευαστή. Αυτό έχει ως αποτέλεσμα ένα αντικείμενο Date που αντιπροσωπεύει την τρέχουσα ημερομηνία και ώρα:

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).

Unix timestamp (αριθμός)

Αν περάσεις έναν αριθμό, αυτός θα ερμηνευτεί ως timestamp. Ένα timestamp είναι ένας ακέραιος αριθμός που αντιπροσωπεύει τον αριθμό των χιλιοστών του δευτερολέπτου που έχουν περάσει από την 1η Ιανουαρίου 1970 UTC+0.

const epoch = new Date(0);
// Thu Jan 01 1970 01:00:00 GMT+0100 (Central European Standard Time)

const another = new Date(1749508766627);
// Tue Jun 10 2025 00:39:26 GMT+0200 (Central European Summer Time)

Κάποιος θα περίμενε ότι το new Date(0) θα δημιουργεί το "πρώτο" αντικείμενο ημερομηνίας, αλλά η JavaScript θα μετατρέψει την ημερομηνία στην τοπική σου ζώνη ώρας, που σημαίνει ότι μόνο όσοι βρίσκονται γύρω από τη ζώνη ώρας GMT / με UTC+0 θα πάρουν στην πραγματικότητα την τιμή του Unix epoch.

ISO 8601 timestamp (συμβολοσειρά)

Μπορείς να περάσεις μια τιμή συμβολοσειράς που αντιπροσωπεύει μια ημερομηνία στον κατασκευαστή του Date. Η μόνη μορφή που είναι συνεπής σε όλες τις υλοποιήσεις είναι η απλοποιημένη εκδοχή των διεθνώς αναγνωρισμένων και τυποποιημένων, λεγόμενων, συμβολοσειρών timestamp ISO 8601.

Μια στιγμή στον χρόνο σε UTC μοιάζει κάπως έτσι:

YYYY-MM-DDTHH:mm:ss.mssZ
YYYYMMDDTHHmmss.mssZ

Όπου γίνονται οι παρακάτω αντικαταστάσεις:

Κλειδί Περιγραφή Προεπιλογή
YYYY Το ημερολογιακό έτος, σε 4 ψηφία
MM Ο ημερολογιακός μήνας, σε 2 ψηφία 01
DD Η ημερολογιακή ημέρα, σε 2 ψηφία 01
T Ένα κυριολεκτικό γράμμα T, που χωρίζει την ημερομηνία από την ώρα
HH Οι ώρες σε 24ωρο ρολόι, 2 ψηφία 00
mm Τα λεπτά, 2 ψηφία 00
ss Τα δευτερόλεπτα, 2 ψηφία 00
mss Τα χιλιοστά του δευτερολέπτου, 3 ψηφία 000
Z Ένα κυριολεκτικό γράμμα Z, ή μια μετατόπιση +/-HH:mm

Το κυριολεκτικό γράμμα Z δηλώνει UTC (χωρίς ζώνη ώρας, χωρίς θερινή ώρα).

Επειδή υπάρχουν προεπιλεγμένες τιμές για τα περισσότερα συστατικά, είναι έγκυρο να παραλείψεις μέρη από το τέλος:

YYYY-MM-DD

Προεπιλέγεται ώρα 00:00:00.000

Αν το timestamp δεν τελειώνει σε Z και δεν τελειώνει με +HH:mm ή -HH:mm (που δηλώνει μετατόπιση ζώνης ώρας), τότε, για ιστορικούς λόγους, ισχύει το εξής:

Όταν λείπει η μετατόπιση ζώνης ώρας, οι μορφές που περιέχουν μόνο ημερομηνία ερμηνεύονται ως ώρα UTC, ενώ οι μορφές ημερομηνίας-ώρας ερμηνεύονται ως τοπική ώρα. Η ερμηνεία ως ώρα UTC οφείλεται σε ένα ιστορικό λάθος της προδιαγραφής, το οποίο δεν ήταν συνεπές με το ISO 8601 αλλά δεν μπορούσε να αλλάξει λόγω συμβατότητας με τον ιστό. Δες το Broken Parser – A Web Reality Issue.

Caution

Άλλες μορφές που γίνονται δεκτές από το Date.parse μπορεί να δουλέψουν ή και όχι. Όταν δουλεύεις με ημερομηνίες στη JavaScript, χρησιμοποίησε πάντα ένα timestamp ISO 8601 όταν μετατρέπεις από string σε Date.

Οι μορφές που περιέχουν μόνο ημερομηνία επιτρέπονται, αλλά δεν υποστηρίζονται όλες οι μορφές ISO 8601. Συμβουλέψου τη σελίδα εξήγησης της απλοποιημένης εκδοχής στο MDN.

Αντικείμενο Date

Ένα υπάρχον αντικείμενο ημερομηνίας μπορεί επίσης να χρησιμοποιηθεί ως όρισμα του κατασκευαστή. Αυτό δημιουργεί ένα αντίγραφο του υπάρχοντος αντικειμένου Date με την ίδια ημερομηνία και ώρα.

const t1 = new Date();
const t2 = new Date(t1);
// Values of t1 and t2 will be the same.

Παροχή μεμονωμένων τιμών για τα συστατικά ημερομηνίας και ώρας

Μπορείς να δημιουργήσεις μια ημερομηνία περνώντας τρεις αριθμούς. Μπορείς να δημιουργήσεις μια ημερομηνία και ώρα περνώντας 6 αριθμούς.

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.

Η δεύτερη τιμή είναι ο month, ο οποίος ξεκινά από το 0 για τον Ιανουάριο και φτάνει μέχρι το 11 για τον Δεκέμβριο.

Date.parse()

Μπορεί να συναντήσεις αναφορές σε μια συνάρτηση ανάλυσης ημερομηνίας, τη Date.parse. Επειδή υπάρχουν μόνο λίγα αναλλοίωτα (αλήθειες) για αυτή τη συνάρτηση και επειδή η υπόλοιπη υλοποίηση δεν προσδιορίζεται (και άρα δεν είναι τυποποιημένη), καλό είναι να μην τη χρησιμοποιείς.

Πρόσβαση στα συστατικά του Date

Υπάρχουν διάφορες μέθοδοι στα αντικείμενα ημερομηνίας που επιστρέφουν τα συστατικά της ημερομηνίας:

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(); // Get the hour in a 24 clock, from 0 to 23
getMinutes(); // Get the minutes, from 0 to 59
getSeconds(); // Get the seconds, from 0 to 59
getMilliseconds(); // Get the milliseconds, from 0 and 999
getDay(); // Get the day of week, from 0 (Sunday) to 6 (Saturday).

Καθεμία από αυτές έχει μια αντίστοιχη παραλλαγή set (π.χ. setFullYear) για να ενημερώσεις την τιμή. Κάθε τιμή που ξεπερνά το όριο μετακυλίεται στο επόμενο συστατικό:

const date = new Date('2025-02-28T12:42:00Z');
// => Fri Feb 28 2025 13:42:00 GMT+0100 (Central European Standard Time)

date.setDate(29);
// there was no February 29th in 2025.

date.getDate();
// => 1

date.toString();
// => Sat Mar 01 2025 13:42:00 GMT+0100 (Central European Standard Time)

Υπάρχουν παραλλαγές UTC για όλες τις μεθόδους που αγνοούν την τοπική ζώνη ώρας.

Μετατροπή από ημερομηνία

Τα αντικείμενα ημερομηνίας έχουν μια μέθοδο getTime() που επιστρέφει το timestamp UNIX σε χιλιοστά του δευτερολέπτου, δηλαδή τον αριθμό των χιλιοστών του δευτερολέπτου από τα μεσάνυχτα της 1ης Ιανουαρίου 1970, UTC. Επιπλέον, υπάρχει μια μέθοδος toISOString() για να μετατρέψεις ένα αντικείμενο ημερομηνίας σε συμβολοσειρά timestamp ISO 8601.

Σύγκριση ημερομηνιών

Οι τελεστές μεγαλύτερο από (>) και μεγαλύτερο ή ίσο με (>=), καθώς και μικρότερο από (<) και μικρότερο ή ίσο με (<=), μπορούν να χρησιμοποιηθούν απευθείας ανάμεσα σε δύο ημερομηνίες ή ανάμεσα σε μια ημερομηνία και έναν αριθμό. Αυτό λειτουργεί επειδή η JavaScript θα προσπαθήσει να μετατρέψει την ημερομηνία σε μια πρωταρχική τιμή.

Advanced

Όταν κάνει μια σύγκριση ανάμεσα σε δύο ημερομηνίες ή σε μια ημερομηνία και έναν αριθμό, η JavaScript καλεί το [Symbol.toPrimitive]("number"), το οποίο εσωτερικά καλεί το date.valueOf(). Το τελευταίο είναι το ίδιο με το να καλέσεις το date.getTime().

Αν δε θέλεις να βασίζεσαι σε αυτή τη συμπεριφορά, μετατρέψε πρώτα σε αριθμό χρησιμοποιώντας το getTime().

Οι ημερομηνίες δε μπορούν να συγκριθούν με ισότητα (== και ===), αλλά το αποτέλεσμα του .getTime() μπορεί.

Οδηγίες

Σε αυτή την άσκηση θα δουλέψεις πάνω σε κάποιες συναρτήσεις για να διαχειρίζεσαι ραντεβού. Το σύστημα αποθηκεύει τα πάντα σε συμβολοσειρές με μορφή ISO 8601, αλλά οι άνθρωποι δεν χρησιμοποιούν έτσι το ημερολόγιο. Χρειάζονται διάφορες συναρτήσεις για τη μετατροπή μεταξύ των διαφόρων μορφών.

1. Δημιούργησε ένα ραντεβού

Δημιούργησε ένα ραντεβού n ημέρες από τώρα, στην τρέχουσα ώρα. Η συνάρτηση παίρνει n ημέρες και επιστρέφει την ώρα του ραντεβού n ημέρες από τώρα.

createAppointment(4, now);
// Given now is Sun Oct 05 2022 23:28:43 GMT+0600 (Bangladesh Standard Time)
// => Sun Oct 09 2022 23:28:43 GMT+0600 (Bangladesh Standard Time)

Αν η δεύτερη παράμετρος now δεν χρησιμοποιηθεί, θα πρέπει να χρησιμοποιηθεί η τρέχουσα ώρα.

2. Μετέτρεψε μια ημερομηνία σε χρονική σήμανση

Διάφορα εργαλεία λειτουργούν μόνο με τη διεθνώς τυποποιημένη μορφή ISO 8601. Γράψε τη συνάρτηση getAppointmentTimestamp που παίρνει μια ημερομηνία και επιστρέφει μια συμβολοσειρά σε αυτή τη μορφή.

const appointment = new Date(Date.UTC(2010, 6, 16, 12, 42, 0, 0));

getAppointmentTimestamp(appointment);
// => '2010-07-16T12:42:00.000Z'

3. Πάρε τις λεπτομέρειες ενός ραντεβού

Οι χρονικές σημάνσεις είναι δύσκολο να διαβαστούν, οπότε μια συνάρτηση που παίρνει τις λεπτομέρειες του ραντεβού θα βοηθήσει. Η συνάρτηση getAppointmentDetails παίρνει μια χρονική σήμανση σε μορφή ISO 8601 και επιστρέφει το έτος, τον μήνα, την ημέρα, την ώρα και το λεπτό.

getAppointmentDetails('2022-04-24T08:15:00.000');
// => { year: 2022, month: 3, date: 24, hour: 8, minute: 15 }

4. Ενημέρωσε ένα ραντεβού με τις δοσμένες επιλογές

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

updateAppointment('2022-02-09T09:20:00.000', { month: 6 });
// => { year: 2022, month: 6, date: 9, hour: 10, minute: 20 }

5. Βρες τον διαθέσιμο χρόνο μεταξύ δύο ραντεβού

Η συνάρτηση θα λάβει δύο ραντεβού (χρονικές σημάνσεις) ως ορίσματα. Πρέπει να επιστρέψεις τη διαφορά μεταξύ αυτών των δύο χρόνων σε δευτερόλεπτα.

Επειδή το μισό δευτερόλεπτο είναι σχεδόν χωρίς νόημα, στρογγυλοποίησε τον αριθμό πριν τον επιστρέψεις.

timeBetween('2022-12-12T09:20:00.000', '2022-12-18T08:30:00.000');
// => 515400

6. Έλεγξε αν ένα ραντεβού είναι έγκυρο τώρα ή όχι

Τέλος, όταν κλείνεται το ραντεβού, το σύστημα πρέπει να ελέγξει αν είναι έγκυρο. Με άλλα λόγια, το ραντεβού πρέπει να είναι στο μέλλον και όχι στο παρελθόν.

Γράψε τη συνάρτηση isValid που παίρνει δύο ορίσματα, μια χρονική σήμανση ραντεβού (συμβολοσειρά) και την τρέχουσα ώρα ως χρονική σήμανση (συμβολοσειρά), και επιστρέφει true αν το ραντεβού είναι στο μέλλον, δεδομένης της τρέχουσας ώρας.

isValid('2022-02-11T23:00:00.000', '2022-02-08T23:00:00.000');
// => true
Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα
JavaScript Exercism

Έτοιμος να ξεκινήσεις την άσκηση Ώρα Ραντεβού;

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