0
votes

The below code is part of a Date extension. However, in Swift 3 I'm getting a few errors that won't go away. I've already changed "NSCalendar" to "Calendar":

func startOfWeek(_ weekday: Int?) -> Date? {
    guard
        let cal = Calendar.current,
        let comp: DateComponents = (cal as Calendar).components([.yearForWeekOfYear, .weekOfYear], from: self) else { return nil }
    comp.to12pm()
    cal.firstWeekday = weekday ?? 1
    return cal.date(from: comp)!
}
func endOfWeek(_ weekday: Int) -> Date? {
    guard
        let cal = Calendar.current,
        var comp: DateComponents = (cal as Calendar).components([.weekOfYear], from: self) else { return nil }
    comp.weekOfYear = 1
    comp.day -= 1
    comp.to12pm()
    return (cal as NSCalendar).date(byAdding: comp, to: self.startOfWeek(weekday)!, options: [])!
}

Lines 3 & 11: let cal = Calendar.current, Initializer for conditional binding must have Optional type, not 'Calendar'

Line 12: I had an error but fixed it by changing "let comp:" to "var comp:"

Line 14: comp.day -= 1 Error: Binary operator '-=' cannot be applied to operands of type 'Int?' and 'Int'

I'm not great with extensions, this code was adapted from an extension I found online, so now updating this is proving to be difficult. Any suggestions?

Troubleshooting (things I tried):

let cal = Calendar?.current,

Error: Type 'Calendar?' has no member 'current'

let cal: Calendar? = Calendar.current,

Error: Explicitly specified type 'Calendar?' adds an additional level of optional to the initializer, making the optional check always succeed

let cal = Calendar.current?,

Error: Cannot use optional chaining on non-optional value of type 'Calendar'

2
You should just follow what the compiler tells you. Some types were Optionals, now they're not: remove your optional bindings. It tells you the struct should be mutable: do it then see how it works now. Etc.Eric Aya
@EricAya I tried a let cal: 'Calendar? = Calendar.current' as well as 'let cal = Calendar?.current' and 'let cal = Calendar.current?' but none worked. So how do I make Calendar optional?Dave G
just a guess, comp.day -= 1 comp.day isn't an lvalue, it is just the return from a method called day on comp... in objective-C there is some magic to make properties work this way (ie it is different than a dot accessor of a classical obj c object), maybe that magic is turned off in swift 3Grady Player
try func startOfWeek(_ weekday: Int? = 1) -> Date? { var cal = Calendar.current cal.firstWeekday = weekday ?? 1 let comp = cal.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self) return cal.date(from: comp) }Leo Dabus
@LeoDabus thanks, I posted the revised code as an answer and credited you.Dave G

2 Answers

0
votes

My date extensions in Swift 3, based on the comments from @LeoDabus

func startOfWeek(_ weekday: Int? = 1) -> Date? {
    var cal = Calendar.current
    cal.firstWeekday = weekday ?? 1
    let comp = cal.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self)
    comp.to12pm()
    return cal.date(from: comp)
}
func endOfWeek(_ weekday: Int) -> Date? {
    let cal = Calendar.current
    var comp = cal.dateComponents([.weekOfYear], from: self)
    comp.weekOfYear = 1
    comp.day? -= 1
    comp.to12pm()
    return cal.date(byAdding: comp, to: self.startOfWeek(weekday)!)!
}

Note I am still mid-migration, so I can only confirm that these eliminate the errors and cannot test them in production yet.

0
votes

You can get every date component separately using this extension:

extension Date {

// MARK:- APP SPECIFIC FORMATS

func app_dateFromString(strDate:String, format:String) -> Date? {

    let dateFormatter:DateFormatter = DateFormatter()
    dateFormatter.dateFormat = format
    if let dtDate = dateFormatter.date(from: strDate){
        return dtDate as Date?
    }
    return nil
}


func app_stringFromDate() -> String{
    let dateFormatter:DateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
    let strdt = dateFormatter.string(from: self as Date)
    if let dtDate = dateFormatter.date(from: strdt){
        return dateFormatter.string(from: dtDate)
    }
    return "--"
}

func app_stringFromDate_timeStamp() -> String{
    return "\(self.hourTwoDigit):\(self.minuteTwoDigit) \(self.AM_PM)  \(self.monthNameShort) \(self.dayTwoDigit)"
}


func getUTCFormateDate(localDate: NSDate) -> String {

    let dateFormatter:DateFormatter = DateFormatter()
    let timeZone: NSTimeZone = NSTimeZone(name: "UTC")!
    dateFormatter.timeZone = timeZone as TimeZone!
    dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm"
    let dateString: String = dateFormatter.string(from: localDate as Date)
    return dateString
}


func combineDateWithTime(date: NSDate, time: NSDate) -> NSDate? {
    let calendar = NSCalendar.current


    let dateComponents = calendar.dateComponents([.year, .month, .day], from: date as Date)

    let timeComponents = calendar.dateComponents([.hour, .minute, .second], from: time as Date)


    let mergedComponments = NSDateComponents()
    mergedComponments.year = dateComponents.year!
    mergedComponments.month = dateComponents.month!
    mergedComponments.day = dateComponents.day!
    mergedComponments.hour = timeComponents.hour!
    mergedComponments.minute = timeComponents.minute!
    mergedComponments.second = timeComponents.second!

    return calendar.date(from: mergedComponments as DateComponents) as NSDate?
}

func getDatesBetweenDates(startDate:NSDate, andEndDate endDate:NSDate) -> [NSDate] {
    let gregorian: NSCalendar = NSCalendar.current as NSCalendar;
    let components = gregorian.components(NSCalendar.Unit.day, from: startDate as Date, to: endDate as Date, options: [])
    var arrDates = [NSDate]()
    for i in 0...components.day!{
        arrDates.append(startDate.addingTimeInterval(60*60*24*Double(i)))
    }
    return arrDates
}


func isGreaterThanDate(dateToCompare: NSDate) -> Bool {
    //Declare Variables
    var isGreater = false

    //Compare Values
    if self.compare(dateToCompare as Date) == ComparisonResult.orderedDescending {
        isGreater = true
    }

    //Return Result
    return isGreater
}

func isLessThanDate(dateToCompare: Date) -> Bool {
    //Declare Variables
    var isLess = false

    //Compare Values
    if self.compare(dateToCompare as Date) == ComparisonResult.orderedAscending {
        isLess = true
    }

    //Return Result
    return isLess
}

func equalToDate(dateToCompare: NSDate) -> Bool {
    //Declare Variables
    var isEqualTo = false

    //Compare Values
    if self.compare(dateToCompare as Date) == ComparisonResult.orderedSame {
        isEqualTo = true
    }

    //Return Result
    return isEqualTo
}


// MARK:- TIME
var timeWithAMPM: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "h:mma"
    dateFormatter.amSymbol = "am"
    dateFormatter.pmSymbol = "pm"
    return dateFormatter.string(from: self as Date)
}




// MARK:- YEAR


var yearFourDigit_Int: Int {
    return Int(self.yearFourDigit)!
}

var yearOneDigit: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "y"
    return dateFormatter.string(from: self as Date)
}
var yearTwoDigit: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yy"
    return dateFormatter.string(from: self as Date)
}
var yearFourDigit: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "yyyy"
    return dateFormatter.string(from: self as Date)
}



// MARK:- MONTH

var monthOneDigit_Int: Int {
    return Int(self.monthOneDigit)!
}
var monthTwoDigit_Int: Int {
    return Int(self.monthTwoDigit)!
}


var monthOneDigit: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "M"
    return dateFormatter.string(from: self as Date)
}
var monthTwoDigit: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "MM"
    return dateFormatter.string(from: self as Date)
}
var monthNameShort: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "MMM"
    return dateFormatter.string(from: self as Date)
}
var monthNameFull: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "MMMM"
    return dateFormatter.string(from: self as Date)
}
var monthNameFirstLetter: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "MMMMM"
    return dateFormatter.string(from: self as Date)
}

// MARK:- DAY

var dayOneDigit_Int: Int {
    return Int(self.dayOneDigit)!
}
var dayTwoDigit_Int: Int {
    return Int(self.dayTwoDigit)!
}

var dayOneDigit: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "d"
    return dateFormatter.string(from: self as Date)
}
var dayTwoDigit: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "dd"
    return dateFormatter.string(from: self as Date)
}
var dayNameShort: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "E"
    return dateFormatter.string(from: self as Date)
}
var dayNameFull: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "EEEE"
    return dateFormatter.string(from: self as Date)
}
var dayNameFirstLetter: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "EEEEE"
    return dateFormatter.string(from: self as Date)
}




// MARK:- AM PM
var AM_PM: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "a"
    return dateFormatter.string(from: self as Date)
}

// MARK:- HOUR


var hourOneDigit_Int: Int {
    return Int(self.hourOneDigit)!
}
var hourTwoDigit_Int: Int {
    return Int(self.hourTwoDigit)!
}
var hourOneDigit24Hours_Int: Int {
    return Int(self.hourOneDigit24Hours)!
}
var hourTwoDigit24Hours_Int: Int {
    return Int(self.hourTwoDigit24Hours)!
}
var hourOneDigit: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "h"
    return dateFormatter.string(from: self as Date)
}
var hourTwoDigit: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "hh"
    return dateFormatter.string(from: self as Date)
}
var hourOneDigit24Hours: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "H"
    return dateFormatter.string(from: self as Date)
}
var hourTwoDigit24Hours: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "HH"
    return dateFormatter.string(from: self as Date)
}

// MARK:- MINUTE

var minuteOneDigit_Int: Int {
    return Int(self.minuteOneDigit)!
}
var minuteTwoDigit_Int: Int {
    return Int(self.minuteTwoDigit)!
}

var minuteOneDigit: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "m"
    return dateFormatter.string(from: self as Date)
}
var minuteTwoDigit: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "mm"
    return dateFormatter.string(from: self as Date)
}


// MARK:- SECOND

var secondOneDigit_Int: Int {
    return Int(self.secondOneDigit)!
}
var secondTwoDigit_Int: Int {
    return Int(self.secondTwoDigit)!
}

var secondOneDigit: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "s"
    return dateFormatter.string(from: self as Date)
}
var secondTwoDigit: String {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "ss"
    return dateFormatter.string(from: self as Date)
}

}