Отримати день тижня за допомогою NSDate


89

Я створив метод, який повинен взяти рядок у формі "РРРР-ММ-ДД" і виплеснути int, який представляє позицію дат щодо тижня, в якому він перебуває (незалежно від того, чи перекривається він між місяцями). Так, наприклад, неділя = 1 понеділок = 2 і так далі.

Ось мій код:

    func getDayOfWeek(today:String)->Int{

    var formatter:NSDateFormatter = NSDateFormatter()
    formatter.dateFormat = "YYYY-MM-DD"
    var todayDate:NSDate = formatter.dateFromString(today)!
    var myCalendar:NSCalendar = NSCalendar(calendarIdentifier: NSGregorianCalendar)
    var myComponents = myCalendar.components(NSCalendarUnit.WeekdayOrdinalCalendarUnit, fromDate: todayDate)
    var weekDay = myComponents.weekdayOrdinal
    return weekDay
}

Я знаю, що NSCalendarUnit.WeekdayOrdinalCalendarце неправильно, але я намагався, думаю, найбільш логічні комбінації. А також базікали, myComponents.weekdayOrdinalнаприклад, використовували mycomponents.dayабо .weekday.

Ось мої варіанти того, що використовувати:

static var EraCalendarUnit: NSCalendarUnit { get }
static var YearCalendarUnit: NSCalendarUnit { get }
static var MonthCalendarUnit: NSCalendarUnit { get }
static var DayCalendarUnit: NSCalendarUnit { get }
static var HourCalendarUnit: NSCalendarUnit { get }
static var MinuteCalendarUnit: NSCalendarUnit { get }
static var SecondCalendarUnit: NSCalendarUnit { get }
static var WeekCalendarUnit: NSCalendarUnit { get }
static var WeekdayCalendarUnit: NSCalendarUnit { get }
static var WeekdayOrdinalCalendarUnit: NSCalendarUnit { get }
static var QuarterCalendarUnit: NSCalendarUnit { get }
static var WeekOfMonthCalendarUnit: NSCalendarUnit { get }
static var WeekOfYearCalendarUnit: NSCalendarUnit { get }
static var YearForWeekOfYearCalendarUnit: NSCalendarUnit { get }
static var CalendarCalendarUnit: NSCalendarUnit { get }
static var TimeZoneCalendarUnit: NSCalendarUnit { get }

Мені незрозуміло, оскільки немає опції DayOfWeekUnit (або чогось подібного).


1
Дивіться: Дати та час форматування ICU для форматування символів.
zaph


1
@Suhaib Якщо ви подивитесь на мої теги, там написано Swift, а не Objective-C. Крім того, код знаходиться в Swift 2.
boidkan

спробуйте наступне "EEEE" у вашому форматі дати
Александрос

Відповіді:


118

Те, що ви шукаєте (якщо я правильно розумію питання), це NSCalendarUnit.CalendarUnitWeekday. Відповідна властивість NSDateComponentsis weekday.

Також зауважте, що формат дати неправильний (повну специфікацію можна знайти тут: http://unicode.org/reports/tr35/tr35-6.html ).

Функцію можна трохи спростити, використовуючи автоматичний висновок типу, також ви багато використовуєте змінні, де достатньо констант. Крім того, функція повинна повертати необов’язковий, який єnil для недійсного вхідного рядка.

Оновлений код для Swift 3 і пізніших версій:

func getDayOfWeek(_ today:String) -> Int? {
    let formatter  = DateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    guard let todayDate = formatter.date(from: today) else { return nil }
    let myCalendar = Calendar(identifier: .gregorian)
    let weekDay = myCalendar.component(.weekday, from: todayDate)
    return weekDay
}

Приклад:

if let weekday = getDayOfWeek("2014-08-27") {
    print(weekday)
} else {
    print("bad input")
}

Оригінальна відповідь для Swift 2:

func getDayOfWeek(today:String)->Int? {

    let formatter  = NSDateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    if let todayDate = formatter.dateFromString(today) {
        let myCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
        let myComponents = myCalendar.components(.Weekday, fromDate: todayDate)
        let weekDay = myComponents.weekday
        return weekDay
    } else {
        return nil
    }
}

Так, саме формат заважав мені. Коли я спробував WeekdayCalendarUnit, я отримував 2 замість 4 і був дуже розгублений! Дякую за посилання, я прочитаю його.
boidkan

1
Я знаю, що це не є частиною оригінального запитання, але це було б гарним місцем для повернення необов’язкового Int у випадку, якщо передана дата не в правильному форматі або якимось чином недійсна.
Mike S

1
Не повинно бути func getDayOfWeek(today:String)->Int?. Якщо примусово розгорнути необов’язковий, він все одно виходить з ладу, чи не так?
МАЄ

1
@HAS: Ви повністю праві, дякую! - У моєму тестовому випадку це не зазнало аварії, оскільки необов’язкове призначення if let ...працює також із неявно розгорнутими додатковими опціями.
Martin R

1
Дякую, Мартінг. За це, щоб зробити вашу відповідь красивішою, ви можете відредагувати її, щоб видалити код swift 2 та зберегти код swift 3. Потім додайте примітку в кінці, де сказано: "Якщо вам потрібен код для швидкого 2, перевірте попереднє редагування" або щось подібне
Suhaib

154

Свіфт 3 і 4

Отримати число дня тижня значно спрощено в Swift 3, оскільки DateComponentsце вже не є обов’язковим. Ось це як розширення:

extension Date {
    func dayNumberOfWeek() -> Int? {
        return Calendar.current.dateComponents([.weekday], from: self).weekday 
    }
}

// returns an integer from 1 - 7, with 1 being Sunday and 7 being Saturday
print(Date().dayNumberOfWeek()!) // 4

Якщо ви шукали письмову локалізовану версію дня тижня:

extension Date {
    func dayOfWeek() -> String? {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "EEEE"
        return dateFormatter.string(from: self).capitalized 
        // or use capitalized(with: locale) if you want
    }
}

print(Date().dayOfWeek()!) // Wednesday

1
Можливо, було б зрозуміліше, якщо ви поставите aDate.dayOfWeek () під Usage.
boidkan

1
Зверніть увагу, що питання полягало в тому, як отримати будній день із рядка у формі "РРРР-ММ-ДД". Звичайно, це спрощується, якщо у вас вже є NSDate.
Martin R

4
Напевно, варто згадати, що якщо ви використовуєте його в напр. подання таблиці, це може сповільнити прокрутку, оскільки створення DateFormatter досить дороге. Якщо ви збираєтеся використовувати його дуже часто, добре, наприклад. створити один екземпляр і надати його під час обчислення усім викликам функції.
Vive

Абсолютно. У такому випадку корисним буде навіть обробник масиву, де ви можете запустити функцію на масиві даних.
brandonscript

1
простіше було б просто відповідь @ david72 нижче: Calendar.current.component (.weekday, from: Date ())
Адам Смака

37

Якщо ви хочете повністю "Неділя", "Понеділок", "Вівторок", "Середа" тощо.

EDIT: насправді є вбудований формат, який повертає локалізовані назви днів:

extension NSDate {
    func dayOfTheWeek() -> String? {        
        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "EEEE"
        return dateFormatter.stringFromDate(self)
    }
}

Моє попереднє рішення (лише для англійської мови):

extension NSDate {

    func dayOfTheWeek() -> String? {
        let weekdays = [
            "Sunday",
            "Monday",
            "Tuesday",
            "Wednesday",
            "Thursday",
            "Friday",
            "Saturday"
        ]

        let calendar: NSCalendar = NSCalendar.currentCalendar()
        let components: NSDateComponents = calendar.components(.Weekday, fromDate: self)
        return weekdays[components.weekday - 1]
    }
}

Вам не потрібно розгортати календар та компоненти, вони гарантовані базовою основою.

Використання:

print(myDate.dayOfTheWeek())

5
EEEEE та EEEEEE дають вам короткі форми днів, наприклад, ср, чт, пт
Матьян

1
Або використовуйте властивість shortWeekdaySymbols календаря, щоб уникнути створення DateFormatter взагалі.
mikepj

22

Проста відповідь (швидко 3):

Calendar.current.component(.weekday, from: Date())

11

У моєму випадку я дотримувався трибуквеного рядка на кожен день. Я змінив функцію @Martin R таким чином:

func getDayOfWeekString(today:String)->String? {
    let formatter  = NSDateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    if let todayDate = formatter.dateFromString(today) {
        let myCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
        let myComponents = myCalendar.components(.Weekday, fromDate: todayDate)
        let weekDay = myComponents.weekday
        switch weekDay {
        case 1:
            return "Sun"
        case 2:
            return "Mon"
        case 3:
            return "Tue"
        case 4:
            return "Wed"
        case 5:
            return "Thu"
        case 6:
            return "Fri"
        case 7:
            return "Sat"
        default:
            print("Error fetching days")
            return "Day"
        }
    } else {
        return nil
    }
}

2
Ви можете використовувати EEE якdateFormat
mrvincenzo

10

Є простіший спосіб. Просто передайте дату рядка наступній функції, вона дасть вам назву дня :)

func getDayNameBy(stringDate: String) -> String
    {
        let df  = NSDateFormatter()
        df.dateFormat = "YYYY-MM-dd"
        let date = df.dateFromString(stringDate)!
        df.dateFormat = "EEEE"
        return df.stringFromDate(date);
    }

2
шукав "EEE". thanx
anoo_radha

9
extension Date {

var weekdayName: String {
    let formatter = DateFormatter(); formatter.dateFormat = "E"
    return formatter.string(from: self as Date)
}

var weekdayNameFull: String {
    let formatter = DateFormatter(); formatter.dateFormat = "EEEE"
    return formatter.string(from: self as Date)
}
var monthName: String {
    let formatter = DateFormatter(); formatter.dateFormat = "MMM"
    return formatter.string(from: self as Date)
}
var OnlyYear: String {
    let formatter = DateFormatter(); formatter.dateFormat = "YYYY"
    return formatter.string(from: self as Date)
}
var period: String {
    let formatter = DateFormatter(); formatter.dateFormat = "a"
    return formatter.string(from: self as Date)
}
var timeOnly: String {
    let formatter = DateFormatter(); formatter.dateFormat = "hh : mm"
    return formatter.string(from: self as Date)
}
var timeWithPeriod: String {
    let formatter = DateFormatter(); formatter.dateFormat = "hh : mm a"
    return formatter.string(from: self as Date)
}

var DatewithMonth: String {
    let formatter = DateFormatter(); formatter.dateStyle = .medium ;        return formatter.string(from: self as Date)
}
}

використання дозволено dayday = Date (). weekdayName


8

Swift 3 Розширення дати

extension Date {
    var weekdayOrdinal: Int {
        return Calendar.current.component(.weekday, from: self)
    }
}

Я додав важливий момент до вашої відповіді, який є сучасною відповіддю тут. Очевидно, не соромтеся розслабитися, якщо вам не подобається! :) Вітаю
Fattie

запитання, яке задавали ціле число
приємне

6

Ви можете використовувати цю таблицю date_formats для перетворення дати в різні формати. Мій найкоротший код:

func getDayOfWeek(today: String) -> Int{
    let formatter:NSDateFormatter = NSDateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    let todayDate = formatter.dateFromString(today)
    formatter.dateFormat = "e" // "eeee" -> Friday
    let weekDay = formatter.stringFromDate(todayDate!)
    return Int(weekDay)!
}
getDayOfWeek("2015-12-18") // 6

Щиро дякую. Це те, що я шукав formatter.dateFormat = "eeee" // "eeee" -> п'ятниця
Мохаммед Абунада

4

SWIFT 5 - День тижня

    extension Date {

        var dayofTheWeek: String {
             let dayNumber = Calendar.current.component(.weekday, from: self)
             // day number starts from 1 but array count from 0
             return daysOfTheWeek[dayNumber - 1]
        }

        private var daysOfTheWeek: [String] {
             return  ["Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat"]
        }
     }

Подовження дати на основі відповіді Фатті


3

Практичне рішення ...

Майте на увазі, що результати - це цілі числа від одного до семи.

(Не від нуля до шести.)

let trivialDayStringsORDINAL = ["", "SUN","MON","TUE","WED","THU","FRI","SAT"]
// note that zero is not used

і потім ...

let dow = Calendar.current.component(.weekday, from: someDate)
print( trivialDayStringsORDINAL[dow] )

3

Тут вже є багато відповідей, але я думаю, що існує інший, можливо, кращий спосіб зробити це за допомогою правильних CalendarAPI.

Я пропоную отримати день тижня, використовуючи weekdaySymbolsвластивість Calendar( docs ) у розширенні до Date:

extension Date {

    /// Returns the day of the week as a `String`, e.g. "Monday"
    var dayOfWeek: String {
        let calendar = Calendar.autoupdatingCurrent
        return calendar.weekdaySymbols[calendar.component(.weekday, from: self) - 1]
    }
}

Це вимагає ініціалізації Dateпершого, що я б зробив, використовуючи спеціальний DateFormatter:

extension DateFormatter {

    /// returns a `DateFormatter` with the format "yyyy-MM-dd".
    static var standardDate: DateFormatter {
        let formatter = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd"
        return formatter
    }
}

Потім це можна викликати за допомогою:

DateFormatter.standardDate.date(from: "2018-09-18")!.dayOfWeek

Чому я віддаю перевагу цьому:

  1. dayOfWeek не повинен дбати про часові пояси, оскільки використовується календар користувача, деякі інші рішення тут відображатимуть неправильний день, оскільки часові пояси не враховуються.
  2. Дуже ймовірно, що вам доведеться використовувати дати в тому ж форматі в інших місцях, то чому б не створити багаторазове використання DateFormatterта не використовувати це замість цього?
  3. weekdaySymbols локалізовано для вас.
  4. weekDaySymbolsможна замінити іншими параметрами, такими як shortWeekdaySymbols"Пн", "Вт" тощо.

Зверніть увагу: Цей приклад DateFormatterтакож не враховує часові пояси чи регіони, вам потрібно буде встановити їх відповідно до того, що вам потрібно. Якщо дати завжди точні, подумайте про встановлення часового поясу TimeZone(secondsFromGMT: 0).


1
Вражає те, що це єдина відповідь, про яку згадується weekdaySymbols, дякую
Фатті

1

Мені знадобилося ще кілька рядків з дати, включаючи дату тижня (наприклад, "5-й") і місяць року (наприклад, серпень). Нижче наведені всі три функції, які я створив на основі функції @Martin R і модифікував для повернення 3 рядків символів:

//Date String Helper Functions
func getDayOfWeek(today:String)->String? {
    let formatter  = NSDateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    if let todayDate = formatter.dateFromString(today) {
        let myCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
        let myComponents = myCalendar.components(.Weekday, fromDate: todayDate)
        let weekDay = myComponents.weekday
        switch weekDay {
        case 1:
            return "Sun"
        case 2:
            return "Mon"
        case 3:
            return "Tue"
        case 4:
            return "Wed"
        case 5:
            return "Thu"
        case 6:
            return "Fri"
        case 7:
            return "Sat"
        default:
            print("Error fetching days")
            return "Day"
        }
    } else {
        return nil
    }
}

func getDateOfMonth(today:String)->String? {
    let formatter  = NSDateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    if let todayDate = formatter.dateFromString(today) {
        let myCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
        let myComponents = myCalendar.components(.Day, fromDate: todayDate)
        let weekDay = myComponents.day
        switch weekDay {
        case 1:
            return "1st"
        case 2:
            return "2nd"
        case 3:
            return "3rd"
        case 4:
            return "4th"
        case 5:
            return "5th"
        case 6:
            return "6th"
        case 7:
            return "7th"
        case 8:
            return "8th"
        case 9:
            return "9th"
        case 10:
            return "10th"
        case 11:
            return "11th"
        case 12:
            return "12th"
        case 13:
            return "13th"
        case 14:
            return "14th"
        case 15:
            return "15th"
        case 16:
            return "16th"
        case 17:
            return "17th"
        case 18:
            return "18th"
        case 19:
            return "19th"
        case 20:
            return "20th"
        case 21:
            return "21st"
        case 22:
            return "22nd"
        case 23:
            return "23rd"
        case 24:
            return "24th"
        case 25:
            return "25th"
        case 26:
            return "26th"
        case 27:
            return "27th"
        case 28:
            return "28th"
        case 29:
            return "29th"
        case 30:
            return "30th"
        case 31:
            return "31st"
        default:
            print("Error fetching Date Of Month")
            return "Day"
        }
    } else {
        return nil
    }
}

func getMonthOfYear(today:String)->String? {
    let formatter  = NSDateFormatter()
    formatter.dateFormat = "yyyy-MM-dd"
    if let todayDate = formatter.dateFromString(today) {
        let myCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
        let myComponents = myCalendar.components(.Month, fromDate: todayDate)
        let month = myComponents.month
        switch month {
        case 1:
            return "Jan"
        case 2:
            return "Feb"
        case 3:
            return "Mar"
        case 4:
            return "Apr"
        case 5:
            return "May"
        case 6:
            return "Jun"
        case 7:
            return "Jul"
        case 8:
            return "Aug"
        case 9:
            return "Sep"
        case 10:
            return "Oct"
        case 11:
            return "Nov"
        case 12:
            return "Dec"
        default:
            print("Error fetching months")
            return "Month"
        }
    } else {
        return nil
    }
}

1

Код SWIFT 2.0 для представлення поточного тижня, починаючи з понеділка.

@IBAction func show (відправник: AnyObject) {

   // Getting Days of week corresponding to their dateFormat

    let calendar = NSCalendar.currentCalendar()
    let dayInt: Int!
    var weekDate: [String] = []
    var i = 2

    print("Dates corresponding to days are")
    while((dayInt - dayInt) + i < 9)
    {
        let weekFirstDate = calendar.dateByAddingUnit(.Day, value: (-dayInt+i), toDate: NSDate(), options: [])
        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "EEEE dd MMMM"
        let dayOfWeekString = dateFormatter.stringFromDate(weekFirstDate!)
        weekDate.append(dayOfWeekString)
        i++
    }
    for i in weekDate
    {
        print(i) //Printing the day stored in array
    }
}

// function to get week day
func getDayOfWeek(today:String)->Int {

    let formatter  = NSDateFormatter()
    formatter.dateFormat = "MMM-dd-yyyy"
    let todayDate = formatter.dateFromString(today)!
    let myCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
    let myComponents = myCalendar.components(.Weekday, fromDate: todayDate)
    let weekDay = myComponents.weekday
    return weekDay
}


@IBAction func DateTitle(sender: AnyObject) {


    // Getting currentDate and weekDay corresponding to it
    let currentDate = NSDate()
    let dateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = "MMM-dd-yyyy"
    let dayOfWeekStrings = dateFormatter.stringFromDate(currentDate)
    dayInt = getDayOfWeek(dayOfWeekStrings)

}

1

Цей код призначений для пошуку цілого поточного тижня. Це написано в Swift 2.0:

var i = 2
var weekday: [String] = []
var weekdate: [String] = []
var weekmonth: [String] = []

@IBAction func buttonaction(sender: AnyObject) {

    let currentDate = NSDate()
    let dateFormatter = NSDateFormatter()
    dateFormatter.dateFormat = "MMM-dd-yyyy"
    let dayOfWeekStrings = dateFormatter.stringFromDate(currentDate)
    let weekdays = getDayOfWeek(dayOfWeekStrings)
    let calendar = NSCalendar.currentCalendar()

    while((weekdays - weekdays) + i < 9)
    {
        let weekFirstDate = calendar.dateByAddingUnit(.Day, value: (-weekdays+i), toDate: NSDate(), options: [])

        let dayFormatter = NSDateFormatter()
        dayFormatter.dateFormat = "EEEE"
        let dayOfWeekString = dayFormatter.stringFromDate(weekFirstDate!)
        weekday.append(dayOfWeekString)

        let dateFormatter = NSDateFormatter()
        dateFormatter.dateFormat = "dd"
        let dateOfWeekString = dateFormatter.stringFromDate(weekFirstDate!)
        weekdate.append(dateOfWeekString)

        let monthFormatter = NSDateFormatter()
        monthFormatter.dateFormat = "MMMM"
        let monthOfWeekString = monthFormatter.stringFromDate(weekFirstDate!)
        weekmonth.append(monthOfWeekString)

        i++
    }

    for(var j = 0; j<7 ; j++)
    {
    let day = weekday[j]
    let date = weekdate[j]
    let month = weekmonth[j]
    var wholeweek = date + "-" + month + "(" + day + ")"
    print(wholeweek)
    }

}

func getDayOfWeek(today:String)->Int {
    let formatter  = NSDateFormatter()
    formatter.dateFormat = "MMM-dd-yyyy"
    let todayDate = formatter.dateFromString(today)!
    let myCalendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
    let myComponents = myCalendar.components(.Weekday, fromDate: todayDate)
    let daynumber = myComponents.weekday
    return daynumber
}

Вихід буде таким:

14 березня (понеділок) 15 березня (вівторок) 16 березня (середа) 17 березня (четвер) 18 березня (п’ятниця) 19 березня (субота) 20 березня (неділя)


1

Swift 3: допоміжна функція Xcode 8:

func getDayOfWeek(fromDate date: Date) -> String? {
    let cal = Calendar(identifier: .gregorian)
    let dayOfWeek = cal.component(.weekday, from: date)
    switch dayOfWeek {
     case 1:
        return "Sunday"
    case 2:
        return "Monday"
    case 3:
        return "Tuesday"
    case 4:
        return "Wednesday"
    case 5:
        return "Thursday"
    case 6:
        return "Friday"
    case 7:
        return "Saturday"
    default:
        return nil
    }
}

1
Це не локалізовано.
Олександр - Відновити Моніку

0

Щоб Swift4 отримав будній день із рядка

   func getDayOfWeek(today:String)->Int {
        let formatter  = DateFormatter()
        formatter.dateFormat = "yyyy-MM-dd"
        let todayDate = formatter.date(from: today)!
        let myCalendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.gregorian)!
        let myComponents = myCalendar.components(NSCalendar.Unit.weekday, from: todayDate)
        let weekDay = myComponents.weekday
        return weekDay!
    }

let weekday = getDayOfWeek(today: "2018-10-10")
print(weekday) // 4

Чим це відрізняється від першого методу у stackoverflow.com/a/25533357/1187415 ?
Martin R
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.