Διαδρομές
/
Julia
Julia
/
Ασκήσεις
/
Κλείσε ραντεβού για ομορφιά
Κλείσε ραντεβού για ομορφιά

Κλείσε ραντεβού για ομορφιά

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

Εισαγωγή

"Οι ημερομηνίες και οι ώρες είναι κάτι που το μαθαίνουμε σε μικρά παιδιά. Πόσο δύσκολο μπορεί να είναι;"

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

Όποιος ασχολείται με μη τετριμμένο προγραμματισμό με ημερομηνίες και ώρες θα πρέπει τουλάχιστον να είναι έτοιμος να κατανοήσει και να μετριάσει πιθανά προβλήματα.

Αυτό το κείμενο θα επιχειρήσει να δώσει μια επισκόπηση του πώς η Julia χειρίζεται τις ημερομηνίες και τις ώρες, αλλά θα χρειαστεί να συμβουλευτείς το εγχειρίδιο για περισσότερες λεπτομέρειες. Υπάρχει επίσης ένα Wikibook που μερικοί αναγνώστες μπορεί να βρουν πιο κατανοητό στις εξηγήσεις του, και περιλαμβάνει ένα χρήσιμο διάγραμμα της ιεραρχίας των τύπων.

Το module Dates

Η περισσότερη βασική λειτουργικότητα βρίσκεται στο Dates, ένα module που περιλαμβάνεται σε μια προεπιλεγμένη εγκατάσταση αλλά δεν αποτελεί μέρος της πρότυπης βιβλιοθήκης.

Για να χρησιμοποιήσεις το module, υπάρχουν δύο επιλογές:

  1. Πρόσθεσε import Dates και μετά βάλε Dates. μπροστά από κάθε κλήση συνάρτησης.
  2. Πρόσθεσε using Dates, που φέρνει ολόκληρο το module στο τρέχον namespace (εκτός από μερικά προβληματικά ονόματα).
# option 1
julia> import Dates

julia> Dates.now()
2025-06-21T16:02:39.080

julia> now()  # wrong: need to include `Dates.` after an import
ERROR: UndefVarError: `now` not defined in `Main`


# option 2
julia> using Dates

julia> now()  # functions are now in the namespace
2025-06-21T16:03:04.161

Το module Dates είναι μεγάλο και περίπλοκο, αλλά παρέχει τέσσερις βασικές κατηγορίες λειτουργικότητας:

  • Το Dates.Date, που περιλαμβάνει ημέρα-μήνα-έτος αλλά όχι ώρα της ημέρας.
  • Το Dates.Time, που περιλαμβάνει ώρα της ημέρας αλλά όχι ημερομηνία.
  • Το Dates.DateTime, που συνδυάζει ημερομηνία και ώρα.
  • Το Dates.Period, που χειρίζεται χρονικά διαστήματα.

Να σημειώσεις ότι ένα DateTime γενικά δεν περιλαμβάνει πληροφορίες ζώνης ώρας (η Python θα το έλεγε "naive" datetime). Μία εξαίρεση είναι το now(), που παίρνει την τοπική ώρα από το ρολόι του συστήματός σου και μπορεί να τη μετατρέψει σε UTC αν χρειάζεται.

Ίσως οι πιο συχνές ανάγκες είναι:

  • Η ανάλυση κάποιας κατάλληλης μορφής εισόδου για να κατασκευαστεί ένας τύπος Dates.
  • Η εξαγωγή της απαιτούμενης αριθμητικής μορφής ή μορφής συμβολοσειράς από έναν τύπο Dates.
  • Η εφαρμογή μιας μετατόπισης σε μια τιμή Date, Time ή DateTime.
  • Ο υπολογισμός του διαστήματος ανάμεσα σε δύο τέτοιες τιμές.
  • Η λήψη της τρέχουσας ημερομηνίας (με today()) ή/και ώρας (με now()).
Note

Για να μειωθεί η οπτική απόσπαση, τα περισσότερα παραδείγματα κώδικα στο υπόλοιπο αυτό το κείμενο προϋποθέτουν using Dates και αποφεύγουν να συμπεριλαμβάνουν το όνομα του module Dates. στις κλήσεις συναρτήσεων.

Μορφές ημερομηνίας και ώρας

Υπάρχουν πολλοί τρόποι να γράψεις ημερομηνίες και ώρες, και συνήθως διαφέρουν από κουλτούρα σε κουλτούρα. Οι ημερομηνίες με μόνο αριθμούς, όπως "7/6/23", είναι διφορούμενες, μπερδεύουν και έχουν οδηγήσει σε πολλά ακριβά λάθη σε πολυεθνικούς οργανισμούς (ο συγγραφέας το λέει αυτό από πικρή προσωπική εμπειρία).

Το διεθνές πρότυπο ορίζεται στο ISO 8601 και έχει δύο βασικά πλεονεκτήματα:

  • Η ανάλυση είναι γρήγορη και μονοσήμαντη.
  • Η ταξινόμηση είναι εύκολη, αφού η ημερομηνία-ώρα μπορεί να αντιμετωπιστεί ως απλό κείμενο και να ταξινομηθεί αλφαβητικά.

Είδαμε σε ένα προηγούμενο παράδειγμα ότι το Date.now() επέστρεψε 2025-06-21T16:03:04.161.

Αυτό συντίθεται από διάφορα μέρη:

  • YYYY-MM-DD για το τμήμα της ημερομηνίας.
  • hh:mm:ss για το τμήμα της ώρας.
  • Προαιρετικά, χιλιοστά του δευτερολέπτου (ή ακόμη μικρότερη μονάδα) μετά την υποδιαστολή.

Άλλες μορφές συμβολοσειρών θα συζητηθούν σε επόμενη ενότητα.

Ημερομηνίες

Το Dates.Date είναι ένας σχετικά απλός τύπος μόνο για ημερομηνίες, χωρίς καμία κατανόηση ωρών ή ζωνών ώρας.

# constructor with year, month, day arguments
julia> date1 = Date(2025, 06, 23)
2025-06-23

# constructor with ISO 8601 string
julia> date2 = Date("2025-06-23")
2025-06-23

julia> date1 == date2
true

julia> typeof(date1)
Date

Υπάρχουν συναρτήσεις πρόσβασης για τα επιμέρους μέρη της ημερομηνίας, και αυτές έρχονται σε ζεύγη που διακρίνονται από το αν γράφονται με πεζά ή κεφαλαία.

# lowercase returns an integer
julia> month(date1)
6

julia> typeof(month(date1))
Int64

# Propercase returns a Period type
julia> Month(date1)
6 months

julia> typeof(Month(date1))
Month

Συναρτήσεις ερωτημάτων

Υπάρχει μια ποικιλία συναρτήσεων με κάποια κατανόηση του ημερολογίου. Το επόμενο παράδειγμα δείχνει μόνο μερικές.

julia> date1
2025-06-23

julia> dayofweek(date1) # 1 = Monday, 7 = Sunday
1

julia> dayname(date1)
"Monday"

julia> daysinmonth(date1)
30

julia> isleapyear(date1)
false

julia> lastdayofmonth(date1)
2025-06-30

Ώρες

Το Dates.Time είναι ο βασικός τύπος για ώρες μόνο. Δεν έχει καμία κατανόηση των ημερομηνιών: οι ώρες επιστρέφουν αυτόματα στο Time(0, 0, 0) τα μεσάνυχτα.

Η πλήρης μορφή του κατασκευαστή είναι Time(hour, min, sec, millisec, microsec) ή το ισοδύναμο σε ISO 8601.

Όλες οι παράμετροι είναι προαιρετικές και έχουν προεπιλεγμένη τιμή 0.

julia> Time(14, 57, 25, 142)
14:57:25.142

julia> Time("14:57:25.142")
14:57:25.142

julia> Time(14, 57, 25, 142, 32)
14:57:25.142032

Όπως και με το Date, τα επιμέρους μέρη είναι διαθέσιμα μέσω συναρτήσεων πρόσβασης:

julia> minute(t) # => integer
57

julia> Minute(t) # => Period
57 minutes

Ημερομηνίες και ώρες

Το Dates.DateTime συνδυάζει τα περισσότερα χαρακτηριστικά των τύπων Date και Time.

julia> dt1 = DateTime(2025, 6, 23, 14, 57, 25, 142)
2025-06-23T14:57:25.142

# date1 and t were defined in previous examples
julia> dt2 = DateTime(date1, t)
2025-06-23T14:57:25.142

Οι παράμετροι έτους, μήνα και ημέρας έχουν προεπιλεγμένη τιμή 1, ενώ όλες οι παράμετροι ώρας έχουν προεπιλεγμένη τιμή 0.

Το να συγκρατείς σωστά όλες αυτές τις παραμέτρους μπορεί να είναι δύσκολο, οπότε η μορφή ISO μπορεί να είναι προτιμότερη για την είσοδο.

Εναλλακτικά, ένα DateTime μπορεί να κατασκευαστεί από ένα Date και ένα Time, όπως στο παραπάνω παράδειγμα.

Περίοδοι

Κάθε συστατικό της ημερομηνίας/ώρας έχει τον δικό του τύπο Period, από το Year μέχρι το Nanosecond, που αντιπροσωπεύει ένα χρονικό διάστημα. Είναι ιδιαίτερα χρήσιμοι για αριθμητικές πράξεις.

julia> dt1
2025-06-23T14:57:25.142

julia> Year(21)
21 years

julia> Second(61)
61 seconds

julia> dt1 + Year(21) - Second(61)
2046-06-23T14:56:24.142

julia> Date(2025, 07, 03) - Date(2025, 04, 25)
69 days

Όταν δουλεύεις με τύπους Period, η Julia προσπαθεί να είναι έξυπνη απέναντι σε ανωμαλίες του ημερολογίου, όπως το μήκος του μήνα, κάνοντας στρογγυλοποίηση όπου χρειάζεται.

# February has fewer days than January
julia> Date(2025, 1, 31) + Month(1) 
2025-02-28

Αναπαραστάσεις συμβολοσειρών

Αναφέραμε προηγουμένως το πρότυπο ISO 8601, που είναι η προεπιλεγμένη αναπαράσταση ημερομηνίας/ώρας της Julia κατά τη μορφοποίηση ή την ανάλυση συμβολοσειρών.

Προφανώς, πολλές άλλες μορφές χρησιμοποιούνται συχνά, συχνά με τρόπους που διαφέρουν από κουλτούρα σε κουλτούρα. Για να τις χειριστεί, η Julia διαθέτει τον τύπο DateFormat, ο οποίος μπορεί να κατασκευαστεί από μια συμβολοσειρά μορφοποίησης οποιασδήποτε πολυπλοκότητας.

# dateformat"" string syntax
julia> dtfmt = dateformat"d/m/y"
dateformat"d/m/y"

julia> typeof(dtfmt)
DateFormat{Symbol("d/m/y"), Tuple{Dates.DatePart{'d'}, Dates.Delim{Char, 1}, Dates.DatePart{'m'}, Dates.Delim{Char, 1}, Dates.DatePart{'y'}}}

# DateFormat constructor
julia> DateFormat("d/m/y")
dateformat"d/m/y"

Το παραπάνω παράδειγμα είναι πολύ απλό, απλώς μια ημερομηνία στη μορφή ημέρα/μήνας/έτος που είναι συνηθισμένη στην Ευρώπη. Δείχνονται δύο παραλλαγές της σύνταξης, αλλά το αποτέλεσμα είναι πανομοιότυπο.

Ένα DateFormat μπορεί στη συνέχεια να χρησιμοποιηθεί για την ανάλυση οποιασδήποτε κατάλληλης συμβολοσειράς:

julia> DateTime("14/7/2023", dtfmt)
2023-07-14T00:00:00

Η δημιουργία ενός DateFormat συνεπάγεται σημαντική επιβάρυνση, οπότε το να κάνεις αυτό το βήμα μόνο μία φορά (όπως εδώ με το dtfmt) βοηθά στις επιδόσεις όταν κάνεις βρόχο πάνω σε πολλές συμβολοσειρές ημερομηνίας/ώρας.

Οι μορφές μπορούν να είναι πολύ πιο περίπλοκες από αυτό, οπότε δες το εγχειρίδιο για λεπτομέρειες.

Το ίδιο DateFormat μπορεί επίσης να χρησιμοποιηθεί για την έξοδο μιας ημερομηνίας/ώρας σε οποιαδήποτε επιθυμητή μορφή συμβολοσειράς, χρησιμοποιώντας τη συνάρτηση Dates.format().

Δυστυχώς, φαίνεται να υπάρχει σύγκρουση namespace με το format (τουλάχιστον από την Julia 1.11.5 και μετά), οπότε είναι καλύτερο να συμπεριλαμβάνεις το πρόθεμα Dates. ακόμη και μετά το using Dates.

julia> dt1
2025-06-23T14:57:25.142

julia> Dates.format(dt1, dateformat"e, u d")
"Mon, Jun 23"

Όπως τεκμηριώνεται, το "e, u d" δίνει τη συντομευμένη κειμενική αναπαράσταση για την ημέρα της εβδομάδας και τον μήνα.

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

Οδηγίες

Σε αυτή την άσκηση θα δουλέψεις πάνω σε μια εφαρμογή προγραμματισμού ραντεβού για ένα σαλόνι ομορφιάς στη Νέα Υόρκη που άνοιξε στις 15 Σεπτεμβρίου του 2012.

Έχεις πέντε εργασίες, οι οποίες όλες θα αφορούν ημερομηνίες ραντεβού. Οι ώρες είναι σε μορφή 24ώρου (χωρίς AM/PM).

1. Ανάλυσε την ημερομηνία ραντεβού που αποτελείται μόνο από αριθμούς

Υλοποίησε τη συνάρτηση schedule_appointment() ώστε να αναλύει μια κειμενική αναπαράσταση μιας ημερομηνίας ραντεβού και να τη μετατρέπει στην αντίστοιχη μορφή DateTime.

Σημείωσε ότι η είσοδος είναι με τη σειρά μήνας/ημέρα/έτος, όπως στις ΗΠΑ.

julia> schedule_appointment("07/25/2023 13:45:00")
2023-07-25T13:45:00

2. Έλεγξε αν ένα ραντεβού έχει ήδη περάσει

Υλοποίησε τη συνάρτηση has_passed() που παίρνει μια ημερομηνία ραντεβού και ελέγχει αν το ραντεβού ήταν κάπου στο παρελθόν:

julia> has_passed(DateTime(1999, 12, 31, 9, 0, 0))
true

3. Έλεγξε αν το ραντεβού είναι το απόγευμα

Υλοποίησε τη συνάρτηση is_afternoon_appointment() που παίρνει μια ημερομηνία ραντεβού και ελέγχει αν το ραντεβού είναι το απόγευμα (>= 12:00 και < 18:00):

julia> is_afternoon_appointment(DateTime(2023, 3, 29, 15, 0, 0))
true

4. Περιέγραψε την ώρα και την ημερομηνία του ραντεβού

Υλοποίησε τη συνάρτηση description() που παίρνει μια ημερομηνία ραντεβού και επιστρέφει μια περιγραφή αυτής της ημερομηνίας και ώρας:

julia> describe(DateTime(2023, 3, 29, 15, 0, 0))
"You have an appointment on Wednesday, March 29, 2023 at 15:00"

5. Επίστρεψε την ημερομηνία επετείου

Υλοποίησε τη συνάρτηση anniversary_date() που επιστρέφει την ημερομηνία επετείου του φετινού έτους, που είναι η 15η Σεπτεμβρίου:

julia> anniversary_date()  # run during 2025
2025-09-15
Επεξεργασία μέσω GitHub Ο σύνδεσμος ανοίγει σε νέο παράθυρο ή καρτέλα
Julia Exercism

Έτοιμος να ξεκινήσεις την άσκηση Κλείσε ραντεβού για ομορφιά;

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