Calendar — τι είναι, ημερολόγιο Date και υπολογισμοί στο Swift

Συγγραφέας: IT Sectr Δημοσιεύτηκε: 2026-07-12 Χρόνος ανάγνωσης: 7 λεπ

Calendar — είναι μια κλάση Foundation που ορίζει το ημερολογιακό σύστημα και παρέχει μεθόδους για ημερολογιακούς υπολογισμούς: εξαγωγή στοιχείων ημερομηνίας, υπολογισμός διαφοράς μεταξύ ημερομηνιών, εύρεση ορίων περιόδων και μετατόπιση ημερομηνιών. Το ημερολόγιο συνδέει τον απόλυτο χρόνο (Date) με αναγνώσιμα από τον άνθρωπο στοιχεία και λαμβάνει υπόψη περιφερειακά χαρακτηριστικά: αρχή της εβδομάδας, ζώνη ώρας και θερινή ώρα. Σύμφωνα με το Apple Developer Documentation (2025), το Foundation υποστηρίζει 17 ημερολογιακά συστήματα — από το Γρηγοριανό έως το Βουδιστικό και το Ιαπωνικό, καθιστώντας το Calendar ένα καθολικό εργαλείο για διεθνοποιημένες εφαρμογές.

Κύρια Σημεία

  • Calendar — κλάση Foundation για ημερολογιακούς υπολογισμούς: εξαγωγή στοιχείων, σύγκριση και μετατόπιση ημερομηνιών.
  • Calendar.current — το ημερολόγιο συστήματος του χρήστη, λαμβάνει αυτόματα υπόψη τις περιφερειακές ρυθμίσεις.
  • 17 ημερολογιακά συστήματα — το Foundation υποστηρίζει Γρηγοριανό, Βουδιστικό, Ιαπωνικό, Εβραϊκό, Ισλαμικό και άλλα.
  • Calendar.dateComponents εξάγει στοιχεία (έτος, μήνα, ημέρα) από το Date λαμβάνοντας υπόψη τη ζώνη ώρας.
  • Calendar.dateInterval επιστρέφει την ημερομηνία έναρξης και λήξης μιας καθορισμένης περιόδου (ημέρα, εβδομάδα, μήνας).

Τι είναι το Calendar στο Foundation;

Calendar — είναι μια κλάση Foundation που υλοποιεί ημερολογιακούς υπολογισμούς βάσει του ICU (International Components for Unicode). Το ημερολόγιο καθορίζει πώς ο απόλυτος χρόνος (Date) αντιστοιχίζεται σε ημερολογιακά στοιχεία: έτος, μήνας, ημέρα, ώρα, λεπτό, δευτερόλεπτο. Χωρίς το Calendar, είναι αδύνατο να γνωρίζουμε ποιο έτος, μήνα και ημέρα είναι σήμερα — το Date από μόνο του δεν περιέχει αυτές τις πληροφορίες.

Το ημερολόγιο λαμβάνει υπόψη τρεις ομάδες παραμέτρων: ημερολογιακό σύστημα (Γρηγοριανό, Βουδιστικό, Ιαπωνικό), ζώνη ώρας και τοπικές ρυθμίσεις. Το Calendar.current συνδυάζει και τις τρεις από τις ρυθμίσεις συστήματος του χρήστη. Το Calendar.autoupdatingCurrent — μια ειδική έκδοση που ενημερώνεται αυτόματα όταν αλλάζουν οι ρυθμίσεις χωρίς επανεκκίνηση της εφαρμογής μέσω του NotificationCenter.

Το ημερολόγιο είναι ένας τύπος τιμής (value type) στο Foundation. Το Calendar(identifier:) δημιουργεί ένα νέο στιγμιότυπο με σταθερές παραμέτρους. Το ημερολόγιο μπορεί να αντιγραφεί, να συγκριθεί με == και να χρησιμοποιηθεί ως κλειδί σε λεξικό. Αυτό επιτρέπει τη δημιουργία ημερολογίων με συγκεκριμένες ρυθμίσεις timeZone και locale για δοκιμές.

Calendar και NSCalendar

Calendar — η έκδοση Swift του Objective-C NSCalendar, με τη γέφυρα as Calendar / as NSCalendar. Στη σύγχρονη Swift, το Calendar χρησιμοποιείται παντού. Το NSCalendar παραμένει για συμβατότητα προς τα πίσω με το Objective-C API. Το Calendar έχει ένα πλήρες σύνολο μεθόδων χωρίς το πρόθεμα NS, με type-safe ορίσματα και Swift προαιρετικότητα.

Thread Safety — το Calendar είναι thread-safe για ανάγνωση. Το δημιουργημένο στιγμιότυπο μπορεί να διαβαστεί με ασφάλεια από πολλά νήματα. Η τροποποίηση ιδιοτήτων (timeZone, locale) δεν είναι thread-safe — για διαφορετικές διαμορφώσεις, δημιουργήστε ξεχωριστά στιγμιότυπα Calendar.

Τύποι ημερολογίων στο Foundation

Το Foundation υποστηρίζει 17 ημερολογιακά συστήματα μέσω της απαρίθμησης Calendar.Identifier. Κάθε σύστημα έχει τους δικούς του κανόνες για δίσεκτα έτη, αριθμό μηνών και αρχή εποχής. Η επιλογή ημερολογίου επηρεάζει όλους τους υπολογισμούς: dateComponents, dateInterval, nextDate.

Κύρια ημερολογιακά συστήματα:

  • .gregorian — διεθνές πρότυπο, 12 μήνες, 365/366 ημέρες, χριστιανική εποχή.
  • .buddhist — Βουδιστικό ημερολόγιο, χρησιμοποιείται στην Ταϊλάνδη, Καμπότζη, Λάος, η εποχή προηγείται του Γρηγοριανού κατά 543 έτη.
  • .japanese — Ιαπωνικό ημερολόγιο κατά εποχές βασιλείας αυτοκρατόρων, 12 μήνες όπως στο Γρηγοριανό.
  • .hebrew — Εβραϊκό ημερολόγιο, 12/13 μήνες, δίσεκτος μήνας Adar II.
  • .islamic — Ισλαμικό ημερολόγιο, 12 σεληνιακούς μήνες, 354/355 ημέρες.
  • .indian — Ινδικό εθνικό ημερολόγιο (Saka), 12 μήνες.

Calendar(identifier: .gregorian) — το πιο συχνά χρησιμοποιούμενο. Αντιστοιχεί στο διεθνές πρότυπο ISO 8601 και είναι το προεπιλεγμένο ημερολόγιο στις περισσότερες χώρες. Για εφαρμογές με διεθνές κοινό, χρησιμοποιήστε το Calendar.current — αντιστοιχεί αυτόματα στο ημερολόγιο συστήματος του χρήστη.

ΑναγνωριστικόΤύποςΠεριοχή χρήσης
.gregorianΗλιακόΔιεθνές
.buddhistΗλιακόΤαϊλάνδη, Καμπότζη
.japaneseΗλιακόΙαπωνία
.hebrewΣεληνιακό-ΗλιακόΙσραήλ
.islamicΣεληνιακόΙσλαμικές χώρες
.chineseΣεληνιακό-ΗλιακόΚίνα

Calendar και DateComponents

DateComponents και Calendar — αχώριστο ζευγάρι. Το Calendar.dateComponents(_:from:) εξάγει στοιχεία από το Date λαμβάνοντας υπόψη τη ζώνη ώρας του ημερολογίου. Το Calendar.date(from:) δημιουργεί Date από DateComponents, συμπληρώνοντας τα πεδία που λείπουν με προεπιλεγμένες τιμές: ημέρα = 1, ώρα = 0, λεπτό = 0, δευτερόλεπτο = 0.

Η μέθοδος Calendar.component εξάγει ένα στοιχείο, το οποίο είναι βολικό για γρήγορο έλεγχο. Η Calendar.dateComponents εξάγει ένα σύνολο στοιχείων σε μία κλήση — αυτό είναι πιο αποδοτικό επειδή το Calendar εκτελεί τους ημερολογιακούς υπολογισμούς μία φορά, όχι για κάθε στοιχείο ξεχωριστά. Για λίστα 3+ στοιχείων, χρησιμοποιείτε πάντα το dateComponents.

Calendar.compare συγκρίνει δύο Date με καθορισμένη ακρίβεια. Η παράμετρος toGranularity καθορίζει μέχρι ποιο στοιχείο θα γίνει η σύγκριση: .year συγκρίνει μόνο το έτος, .month — έτος και μήνα, .day — έτος, μήνα, ημέρα. Αυτό είναι βολικό για τον έλεγχο εάν δύο ημερομηνίες ανήκουν στην ίδια ημέρα, χωρίς να λαμβάνεται υπόψη η ώρα.

swift
let calendar = Calendar.current
let now = Date()

// Εξαγωγή ενός στοιχείου
let year = calendar.component(.year, from: now)

// Εξαγωγή συνόλου στοιχείων
let comps = calendar.dateComponents(
    [.year, .month, .day], from: now
)

// Σύγκριση με ακρίβεια ημέρας
let isSameDay = calendar.compare(date1, to: date2,
                                  toGranularity: .day) == .orderedSame

// Ελέγξτε εάν η ημερομηνία είναι σήμερα
let isToday = calendar.isDateInToday(someDate)

Calendar.isDateInToday, isDateInTomorrow, isDateInYesterday — μέθοδοι για σχετικούς ελέγχους. Η Calendar.isDate(_:inSameDayAs:) ελέγχει εάν δύο ημερομηνίες πέφτουν στην ίδια ημερολογιακή ημέρα λαμβάνοντας υπόψη τη ζώνη ώρας του ημερολογίου. Αυτές οι μέθοδοι χρησιμοποιούν το Calendar.compare εσωτερικά και είναι βελτιστοποιημένες για συχνή κλήση.

Υπολογισμοί Calendar

Calendar.dateInterval — μία από τις πιο χρήσιμες μεθόδους για αναλυτικά στοιχεία και UI. Επιστρέφει το DateInterval για το καθορισμένο στοιχείο: έναρξη και λήξη ημέρας, εβδομάδας, μήνα, έτους. Το DateInterval περιέχει start (Date) και end (Date) — τα όρια της περιόδου. Για παράδειγμα, το dateInterval(of: .weekOfYear, for: Date()) επιστρέφει την έναρξη της Δευτέρας και τη λήξη της Κυριακής της τρέχουσας εβδομάδας.

Calendar.date με byAdding — μέθοδος για μετατόπιση ημερομηνίας. Το Calendar.date(byAdding: .day, value: 7, to: Date()) επιστρέφει την ημερομηνία σε μία εβδομάδα. Το Calendar.date(byAdding: DateComponents) — μια πιο ευέλικτη έκδοση, που επιτρέπει τη μετατόπιση πολλών στοιχείων ταυτόχρονα: +1 μήνας +3 ημέρες. Το Calendar λαμβάνει αυτόματα υπόψη το διαφορετικό μήκος των μηνών και τα δίσεκτα έτη.

Calendar.nextDate αναζητά την επόμενη ημερομηνία που ταιριάζει με τα καθορισμένα DateComponents. Η παράμετρος matchingPolicy καθορίζει τη συμπεριφορά σε περίπτωση μη αντιστοιχίας: .nextTime — επόμενη αντιστοιχία σε χρόνο, .nextTimePreservingSmallerComponents — διατηρεί τα λεπτά και δευτερόλεπτα από την αρχική ημερομηνία, .strict — απαιτεί ακριβή αντιστοιχία.

swift
let calendar = Calendar.current
let today = Date()

// Αρχή και τέλος εβδομάδας
let weekInterval = calendar.dateInterval(
    of: .weekOfYear, for: today
)!

// Μετατόπιση κατά 1 μήνα
let nextMonth = calendar.date(
    byAdding: .month, value: 1, to: today
)!

// Μετατόπιση μέσω DateComponents
var delta = DateComponents()
delta.month = 1
delta.day = 3
let shifted = calendar.date(byAdding: delta, to: today)!

// Επόμενη Παρασκευή 13
let friday13Components = DateComponents(
    weekday: 6, day: 13
)
let nextFriday13 = calendar.nextDate(
    after: today, matching: friday13Components,
    matchingPolicy: .nextTime
)

EnumerateDates — μια ισχυρή μέθοδος για επανάληψη ημερομηνιών βάσει προτύπου. Το Calendar.enumerateDates(startingAfter:matching:matchingPolicy:using:) καλεί ένα μπλοκ για κάθε αντιστοιχία μέχρι το μπλοκ να επιστρέψει stop = true. Χρησιμοποιείται για τη δημιουργία επαναλαμβανόμενων γεγονότων σε ημερολόγια και προγράμματα. Η μέθοδος είναι πιο αποδοτική από τον χειροκίνητο βρόχο με nextDate, επειδή είναι βελτιστοποιημένη από το ICU.

TimeZone και Locale

TimeZone — αναπόσπαστο μέρος του Calendar. Η ζώνη ώρας καθορίζει σε ποια ημερολογιακή ώρα αντιστοιχεί το απόλυτο Date. Το ίδιο Date σε UTC και στη Μόσχα δίνει διαφορετικά στοιχεία: το Date() σε UTC μπορεί να δείχνει 10:00, και σε MSK — 13:00. Το Calendar.timeZone είναι από προεπιλογή ίσο με το TimeZone.current.

Locale επηρεάζει την πρώτη ημέρα της εβδομάδας, τον ελάχιστο αριθμό ημερών στην πρώτη εβδομάδα του έτους (minDaysInFirstWeek) και τα ονόματα μηνών/ημερών της εβδομάδας (κατά τη μετατροπή μέσω DateFormatter). Το Calendar.locale είναι από προεπιλογή ίσο με το Locale.current. Στις ελληνικές τοπικές ρυθμίσεις, η εβδομάδα ξεκινά τη Δευτέρα, στις αμερικανικές — την Κυριακή.

Calendar.availableIdentifiers επιστρέφει μια λίστα όλων των υποστηριζόμενων αναγνωριστικών ημερολογίου. static property Calendar.availableCalendarIdentifiers — ένας πίνακας συμβολοσειρών με τα ίδια αναγνωριστικά. Χρησιμοποιείται για τη δημιουργία UI επιλογής ημερολογίου και για τον έλεγχο διαθεσιμότητας ενός συγκεκριμένου ημερολογιακού συστήματος στη συσκευή.

swift
// Ημερολόγιο με συγκεκριμένη ζώνη ώρας
var utcCalendar = Calendar(identifier: .gregorian)
utcCalendar.timeZone = TimeZone(identifier: "UTC")!

// Ημερολόγιο με ελληνικές τοπικές ρυθμίσεις
var russianCalendar = Calendar(identifier: .gregorian)
russianCalendar.locale = Locale(identifier: "ru_RU")

// Πρώτη ημέρα εβδομάδας εξαρτάται από το locale
let firstWeekday = russianCalendar.firstWeekday
// 2 = Δευτέρα (στο el_GR)

// Λίστα διαθέσιμων ημερολογίων
for identifier in Calendar.availableIdentifiers {
    print(identifier)
}

firstWeekday — η ιδιότητα του Calendar που καθορίζει ποια ημέρα της εβδομάδας θεωρείται πρώτη. Στις ελληνικές τοπικές ρυθμίσεις, Sunday = 2 (Δευτέρα πρώτη). Στις αμερικανικές, Sunday = 1. Αυτό επηρεάζει τη λειτουργία των weekOfMonth και weekOfYear: η ίδια ημερομηνία μπορεί να αποδοθεί σε διαφορετικούς αριθμούς εβδομάδας σε διαφορετικές τοπικές ρυθμίσεις. Για εφαρμογές με ημερομηνίες, χρησιμοποιήστε το Calendar.current ή ορίστε ρητά το firstWeekday.

Παραδείγματα εργασίας με το Calendar

Ας εξετάσουμε πρακτικά σενάρια που επιδεικνύουν τις δυνατότητες του Calendar. Κάθε παράδειγμα λύνει μια συγκεκριμένη εργασία ανάπτυξης iOS και δείχνει τον σωστό τρόπο χρήσης ημερολογιακών υπολογισμών.

Έλεγχος: η ημερομηνία είναι σε αυτόν τον μήνα;

Calendar.dateInterval(of: .month, for:) επιστρέφει τα όρια του τρέχοντος μήνα. Ο έλεγχος εάν το Date εμπίπτει σε αυτό το διάστημα — ο ταχύτερος τρόπος για να προσδιοριστεί εάν η ημερομηνία ανήκει στον τρέχοντα μήνα. Εναλλακτικός τρόπος — Calendar.compare με granularity .month: εάν το αποτέλεσμα είναι .orderedSame, τότε ο μήνας ταιριάζει.

swift
func isInCurrentMonth(_ date: Date) -> Bool {
    let calendar = Calendar.current
    let monthInterval = calendar.dateInterval(
        of: .month, for: Date()
    )!
    return monthInterval.contains(date)
}

// Αριθμός ημερών σε ένα μήνα
func daysInMonth(for date: Date) -> Int {
    let calendar = Calendar.current
    return calendar.range(
        of: .day, in: .month, for: date
    )?.count ?? 0
}

// Προσθήκη μηνών με σωστή ολοκλήρωση
func addMonths(_ months: Int, to date: Date) -> Date {
    let calendar = Calendar.current
    return calendar.date(
        byAdding: .month, value: months, to: date
    )!
}

Calendar.range(of:in:for:) επιστρέφει το εύρος των επιτρεπόμενων τιμών για το καθορισμένο στοιχείο στο πλαίσιο ενός άλλου στοιχείου. Για παράδειγμα, το range(of: .day, in: .month, for: date) επιστρέφει 1..<32 για μήνες με 31 ημέρες ή 1..<29 για τον Φεβρουάριο μη δίσεκτου έτους. Αυτός είναι ο σωστός τρόπος για να μάθετε τον αριθμό των ημερών σε έναν μήνα, όχι η χρήση hardcode τιμών.

Προσθήκη μηνών μέσω του Calendar.date(byAdding:value:to:) χειρίζεται σωστά τις ημερομηνίες ορίων. Εάν στις 31 Ιανουαρίου προστεθεί 1 μήνας, το Calendar επιστρέφει 28 Φεβρουαρίου (ή 29 σε δίσεκτο έτος), όχι 3 Μαρτίου, όπως θα συνέβαινε με απλή προσθήκη 30 ημερών μέσω TimeInterval. Αυτός είναι ένας ακόμη λόγος να μην χρησιμοποιείτε το TimeInterval για ημερολογιακούς υπολογισμούς.

Μέθοδος CalendarΣκοπόςΠαράδειγμα
dateIntervalΌρια περιόδουΈναρξη και λήξη μήνα
range(of:in:for:)Εύρος στοιχείουΗμέρες στον τρέχοντα μήνα
date(byAdding:)Μετατόπιση ημερομηνίας+1 μήνας από σήμερα
isDateInTodayΈλεγχος εάν είναι σήμεραΕίναι η ημερομηνία σήμερα
compare(toGranularity:)Σύγκριση με ακρίβειαΊδια ημέρα χωρίς ώρα

Συχνές Ερωτήσεις

Ποια είναι η διαφορά μεταξύ Calendar.current και Calendar(identifier: .gregorian);

Calendar.current επιστρέφει το ημερολόγιο από τις ρυθμίσεις συστήματος του χρήστη — μπορεί να μην είναι Γρηγοριανό (για παράδειγμα, Βουδιστικό στην Ταϊλάνδη). Calendar(identifier: .gregorian) δημιουργεί πάντα ένα Γρηγοριανό ημερολόγιο ανεξάρτητα από τις ρυθμίσεις. Για εμφάνιση ημερομηνιών, χρησιμοποιήστε το Calendar.current, για επιχειρηματική λογική — το ρητά επιλεγμένο αναγνωριστικό.

Γιατί το Calendar.date(byAdding: .month, value: 1) μερικές φορές επιστρέφει την ίδια ημερομηνία;

Αυτό σχετίζεται με το διαφορετικό μήκος των μηνών. Εάν η τρέχουσα ημερομηνία είναι 31 Ιανουαρίου, η προσθήκη 1 μήνα δίνει 28 Φεβρουαρίου, επειδή ο Φεβρουάριος δεν έχει 31 ημέρες. Το Calendar συμπληρώνει αυτόματα την ημερομηνία μέχρι την τελευταία επιτρεπόμενη ημέρα του μήνα. Για ακριβή έλεγχο, χρησιμοποιήστε το DateComponents με day: 1 για μετάβαση στην πρώτη ημέρα του μήνα.

Ποιο ημερολόγιο χρησιμοποιεί το DateFormatter από προεπιλογή;

DateFormatter χρησιμοποιεί το Calendar.current — το ημερολόγιο συστήματος του χρήστη. Εάν η εφαρμογή πρέπει πάντα να εμφανίζει ημερομηνίες στο Γρηγοριανό ημερολόγιο ανεξάρτητα από τις ρυθμίσεις, ορίστε το formatter.calendar = Calendar(identifier: .gregorian). Αυτό εγγυάται ομοιόμορφη εμφάνιση για όλους τους χρήστες.

Πώς μπορώ να ελέγξω εάν ένα έτος είναι δίσεκτο μέσω του Calendar;

Calendar.range(of: .day, in: .year, for: date) επιστρέφει 365 ή 366 ημέρες. Απλούστερα: Calendar.date(from: DateComponents(year: έτος, month: 2, day: 29)) != nil — εάν υπάρχει 29 Φεβρουαρίου, το έτος είναι δίσεκτο. Το Calendar λαμβάνει υπόψη του τους κανόνες για το συγκεκριμένο ημερολογιακό σύστημα.

Μπορεί να αλλάξει το firstWeekday μετά τη δημιουργία του Calendar;

Ναι, η ιδιότητα firstWeekday είναι εγγράψιμη. Η αλλαγή επηρεάζει το weekOfMonth, το weekOfYear και όλους τους υπολογισμούς που σχετίζονται με αριθμούς εβδομάδων. Κατά τον ορισμό locale = Locale(identifier: "el_GR"), το firstWeekday γίνεται αυτόματα 2 (Δευτέρα). Η χειροκίνητη ρύθμιση παρακάμπτει την τιμή από το locale.

Σύνοψη

  • Calendar — κλάση Foundation για ημερολογιακούς υπολογισμούς, που συνδέει το Date με αναγνώσιμα από τον άνθρωπο στοιχεία μέσω DateComponents.
  • 17 ημερολογιακά συστήματα υποστηρίζονται από το Foundation — από το Γρηγοριανό έως το Βουδιστικό και το Ιαπωνικό, με αυτόματη λήψη υπόψη περιφερειακών κανόνων.
  • Calendar.current αντιστοιχεί στο ημερολόγιο συστήματος του χρήστη — χρησιμοποιήστε το για UI και DateFormatter.
  • Calendar.dateInterval και Calendar.range — βασικές μέθοδοι για εργασία με όρια περιόδων και εύρη στοιχείων.
  • Calendar.date(byAdding:) χειρίζεται σωστά το διαφορετικό μήκος μηνών και τα δίσεκτα έτη — μην το αντικαθιστάτε με αριθμητική TimeInterval.
  • TimeZone και Locale ως ιδιότητες του Calendar επηρεάζουν όλους τους ημερολογιακούς υπολογισμούς — ορίστε τα ρητά για προβλέψιμη συμπεριφορά.
  • firstWeekday καθορίζεται από τις τοπικές ρυθμίσεις και επηρεάζει τους αριθμούς εβδομάδων — για παγκόσμιες εφαρμογές, ορίστε το ρητά ή χρησιμοποιήστε το Calendar.current.

Θα αναπτύξουμε μια εφαρμογή για κινητά έτοιμη για χρήση

Η IT Sectr δημιουργεί εφαρμογές iOS και Android για νεοφυείς επιχειρήσεις και επιχειρήσεις από το 2017. Θα σας συμβουλεύσουμε και θα προτείνουμε την καλύτερη λύση.

Συζήτηση έργου

Διαβάστε επίσης