"Οι ημερομηνίες και οι ώρες είναι κάτι που το μαθαίνουμε σε μικρά παιδιά. Πόσο δύσκολο μπορεί να είναι;"
Πολλοί προγραμματιστές έχουν κάνει αυτό το λάθος, και η εμπειρία που ακολουθεί συνήθως έχει άσχημη επίδραση στην υγεία και την ευτυχία τους.
Όποιος ασχολείται με μη τετριμμένο προγραμματισμό με ημερομηνίες και ώρες θα πρέπει τουλάχιστον να είναι έτοιμος να κατανοήσει και να μετριάσει πιθανά προβλήματα.
Αυτό το κείμενο θα επιχειρήσει να δώσει μια επισκόπηση του πώς η Julia χειρίζεται τις ημερομηνίες και τις ώρες, αλλά θα χρειαστεί να συμβουλευτείς το εγχειρίδιο για περισσότερες λεπτομέρειες. Υπάρχει επίσης ένα Wikibook που μερικοί αναγνώστες μπορεί να βρουν πιο κατανοητό στις εξηγήσεις του, και περιλαμβάνει ένα χρήσιμο διάγραμμα της ιεραρχίας των τύπων.
Dates
Η περισσότερη βασική λειτουργικότητα βρίσκεται στο Dates, ένα module που περιλαμβάνεται σε μια προεπιλεγμένη εγκατάσταση αλλά δεν αποτελεί μέρος της πρότυπης βιβλιοθήκης.
Για να χρησιμοποιήσεις το module, υπάρχουν δύο επιλογές:
import Dates και μετά βάλε Dates. μπροστά από κάθε κλήση συνάρτησης.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()).Για να μειωθεί η οπτική απόσπαση, τα περισσότερα παραδείγματα κώδικα στο υπόλοιπο αυτό το κείμενο προϋποθέτουν 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).
Υλοποίησε τη συνάρτηση schedule_appointment() ώστε να αναλύει μια κειμενική αναπαράσταση μιας ημερομηνίας ραντεβού και να τη μετατρέπει στην αντίστοιχη μορφή DateTime.
Σημείωσε ότι η είσοδος είναι με τη σειρά μήνας/ημέρα/έτος, όπως στις ΗΠΑ.
julia> schedule_appointment("07/25/2023 13:45:00")
2023-07-25T13:45:00
Υλοποίησε τη συνάρτηση has_passed() που παίρνει μια ημερομηνία ραντεβού και ελέγχει αν το ραντεβού ήταν κάπου στο παρελθόν:
julia> has_passed(DateTime(1999, 12, 31, 9, 0, 0))
true
Υλοποίησε τη συνάρτηση is_afternoon_appointment() που παίρνει μια ημερομηνία ραντεβού και ελέγχει αν το ραντεβού είναι το απόγευμα (>= 12:00 και < 18:00):
julia> is_afternoon_appointment(DateTime(2023, 3, 29, 15, 0, 0))
true
Υλοποίησε τη συνάρτηση description() που παίρνει μια ημερομηνία ραντεβού και επιστρέφει μια περιγραφή αυτής της ημερομηνίας και ώρας:
julia> describe(DateTime(2023, 3, 29, 15, 0, 0))
"You have an appointment on Wednesday, March 29, 2023 at 15:00"
Υλοποίησε τη συνάρτηση anniversary_date() που επιστρέφει την ημερομηνία επετείου του φετινού έτους, που είναι η 15η Σεπτεμβρίου:
julia> anniversary_date() # run during 2025
2025-09-15
Γράψου στο Exercism για να μάθεις και να κατακτήσεις Julia με 35 έννοιες128 ασκήσεις και πραγματική καθοδήγηση από ανθρώπους, όλα δωρεάν.