Is there a built in way to use DateFormatter to get value in the format of "Sun Sep 27 at 4pm" - swift

I have the following formatter:
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
dateFormatter.timeStyle = .short
dateFormatter.doesRelativeDateFormatting = true
My goal is to turn my dates into strings like:
Today at 3pm
Tomorrow at 3pm
Sun Sep 27 at 3pm
It works great for dates that are today or tomorrow, but for dates beyond that I want the following format:
"Sun Sep 27 at 4pm"
When I print the result of dateFormatter.string(from: DATE) for a date 3 days from now, I get the following:
Sep 27, 2020 at 4 PM
Is there a way to customize the dateStyle so I can instead get the desired string? I messed around with .full, .short, etc. but want to customize it my way.

Here is a Locale-independent solution:
Check if the Date is relative:
For this you can use Calendar functions .isDateInYesterday(date:) etc.
private func isDateRelative(_ date: Date) -> Bool {
Calendar.current.isDateInYesterday(date)
|| Calendar.current.isDateInToday(date)
|| Calendar.current.isDateInTomorrow(date)
}
If it's relative replace the date part with the date in the localizedFormat but keep the time part intact.
DateFormatter extension
extension DateFormatter {
func relativeStringWithFormat(from date: Date, localizedFormat: String) -> String {
if isDateRelative(date) {
return relativeDateTimeString(from: date)
}
let dateStr = localizedDateString(from: date, localizedFormat: localizedFormat)
let timeStr = relativeTimeString(from: date)
return dateStr + timeStr
}
private func relativeDateTimeString(from date: Date) -> String {
dateStyle = .medium
timeStyle = .short
doesRelativeDateFormatting = true
return string(from: date)
}
private func relativeDateString(from date: Date) -> String {
dateStyle = .medium
timeStyle = .none
doesRelativeDateFormatting = true
return string(from: date)
}
private func relativeTimeString(from date: Date) -> String {
relativeDateTimeString(from: date).replacingOccurrences(of: relativeDateString(from: date), with: "")
}
private func localizedDateString(from date: Date, localizedFormat: String) -> String {
setLocalizedDateFormatFromTemplate(localizedFormat)
doesRelativeDateFormatting = false
return string(from: date)
}
private func isDateRelative(_ date: Date) -> Bool {
Calendar.current.isDateInYesterday(date)
|| Calendar.current.isDateInToday(date)
|| Calendar.current.isDateInTomorrow(date)
}
}
Testing
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US")
let today = Date()
let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: today)!
let nextWeek = Calendar.current.date(byAdding: .day, value: 7, to: today)!
let localizedFormat = "EEE d MMM"
print(dateFormatter.relativeStringWithFormat(from: today, localizedFormat: localizedFormat))
// Today at 6:20 PM
print(dateFormatter.relativeStringWithFormat(from: tomorrow, localizedFormat: localizedFormat))
// Tomorrow at 6:20 PM
print(dateFormatter.relativeStringWithFormat(from: nextWeek, localizedFormat: localizedFormat))
// Sat, Oct 3 at 6:20 PM

Try it like this:
dateformater.dateformat = "E, d MMM yyyy HH:mm:ss"
Output:
Wed, 12 Sep 2018 14:11:54

Here's a DateFormatter subclass that should give you what you want. Note that I handled the "Yesterday" case even though you didn't mention it in your question. Also note the if you want to display times other than just the hour portion you'll need to adjust the "ha" part of the dateFormat string.
class MyDateFormatter: DateFormatter {
override init() {
super.init()
amSymbol = "am"
pmSymbol = "pm"
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func string(from date: Date) -> String {
setDateFormat(forDate: date)
return super.string(from: date)
}
private func setDateFormat(forDate date: Date) {
if calendar.isDateInYesterday(date) {
dateFormat = "'Yesterday' 'at' ha"
return
} else if calendar.isDateInToday(date) {
dateFormat = "'Today' 'at' ha"
return
} else if calendar.isDateInTomorrow(date) {
dateFormat = "'Tomorrow' 'at' ha"
return
}
dateFormat = "E MMM d 'at' ha"
}
}
Just use it as you would a normal DateFormatter:
let formatter = MyDateFormatter()
let dateStr = formatter.string(from: Date())
print(dateStr) // Today at 12pm

The quickest way to get what you want would just be
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "EEEE MMM d 'at' ha"
If you want to ensure the AM and PM are lowercased, you could add
dateFormatter.amSymbol = "am"
dateFormatter.pmSymbol = "pm"

Related

Can't Convert Date Format Into Display Date In Swift

I've been trying to take a date saved in the format of "Thu Nov 12 2020 07:00:00 GMT+0000 (Greenwich Mean Time)" and convert it into the format of "MMM d, yyyy", however I am unsuccessful in doing so.
import Foundation
extension String {
// Example date read in from database.
// "Thu Nov 12 2020 07:00:00 GMT+0000 (Greenwich Mean Time)"
func convertToDate() -> Date? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "E, d MMM yyyy HH:mm:ss Z"
dateFormatter.locale = Locale(identifier: "en_US_POSSIX")
dateFormatter.timeZone = .current
return dateFormatter.date(from: self)
}
func convertToDisplayFormat() -> String {
guard let date = self.convertToDate() else { return "N/A"}
return date.convertToMonthDayTimeFormat()
}
}
import Foundation
extension Date {
func convertToMonthDayTimeFormat() -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM d, yyyy"
print(dateFormatter.string(from: self))
return dateFormatter.string(from: self)
}
}
And then in the file in which I read in the data the code is
cell.appointmentTime?.text = "\(tableData.date!.convertToDisplayFormat())"
You should always set your dateFormat locale to "en_US_POSIX" before setting the dateFormat. Btw it looks like that your date string you are reading from database is always in UTC format, if that is the case you should set your dateFormatter timezone to zero secondsFromGMT and escape your date string timezone:
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSSIX")
dateFormatter.dateFormat = "EEE MMM dd yyyy HH:mm:ss 'GMT+0000 (Greenwich Mean Time)'"
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
dateFormatter.date(from: "Thu Nov 12 2020 07:00:00 GMT+0000 (Greenwich Mean Time)")
You should also create a static date formatter to avoid creating a new one every time you call this method:
extension Formatter {
static let customDate: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSSIX")
dateFormatter.dateFormat = "EEE MMM dd yyyy HH:mm:ss 'GMT+0000 (Greenwich Mean Time)'"
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
return dateFormatter
}()
static let yyyyMMMd: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.setLocalizedDateFormatFromTemplate("yyyyMMMd")
return dateFormatter
}()
}
extension String {
func convertToDate() -> Date? {
Formatter.customDate.date(from: self)
}
func convertToDisplayFormat() -> String {
convertToDate()?.convertToMonthDayTimeFormat() ?? "N/A"
}
}
extension Date {
func convertToMonthDayTimeFormat() -> String {
Formatter.yyyyMMMd.string(from: self)
}
}
Playground testing:
"Thu Nov 12 2020 07:00:00 GMT+0000 (Greenwich Mean Time)".convertToDisplayFormat() // "Nov 12, 2020"

Swift Date Timezone Issue

extension Formatter {
static let iso8601: DateFormatter = {
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.timeZone = TimeZone.init(identifier: "America/New_York")
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
return formatter
}()
}
extension Date {
var iso8601: String {
return Formatter.iso8601.string(from: self)
}
}
extension String {
var dateFromISO8601: Date? {
return Formatter.iso8601.date(from: self) // "Mar 22, 2017, 10:22 AM"
}
}
let dateFormat:String = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
let strDate: String = "2017-10-09T00:00:00.966Z"
if let dateFromString = strDate.dateFromISO8601
{
print(dateFromString.iso8601)
}
Ok, so it does not do anything with the dateFormatter.date(from: sweDate)!) then? How can I get the string value to Date?
As per my knowledge Date doesn't store the time zone so it always prints the UTC time no matter what the time zone i have used upon formatting.
So what is the solution as i have to compare my local date with the converted date. which i cannot compare with the string.
Any help is appreciated.
You should use Calendar method dateComponents(in: TimeZone) to check the relative date components in a different time zone as follow:
let dateString = "2017-10-09T18:00:00.000Z"
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "en_US_POSIX")
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSXXXXX"
let date = formatter.date(from: dateString)! // "Oct 9, 2017 at 3:00 PM" in Brazil
// "Oct 9, 2017 at 2:00 PM" in New York
let components = Calendar.current.dateComponents(in: TimeZone(identifier: "America/New_York")!, from: date) //calendar: gregorian (fixed) timeZone: America/New_York (fixed) era: 1 year: 2017 month: 10 day: 9 hour: 14 minute: 0 second: 0 nanosecond: 0 weekday: 2 weekdayOrdinal: 2 quarter: 0 weekOfMonth: 2 weekOfYear: 41 yearForWeekOfYear: 2017 isLeapMonth: false
if 8..<16 ~= components.hour! {
print("store is open in NY"). // "store is open in NY\n"
}

Is there a date only (no time) class in Swift?

Is there a date-only (no time) class in Swift? (or Foundation classes)
(as an aside if there is not but there is a well-known/popular open-source library that implements this if you could mention this)
There isn't a date only class in Foundation, but you can strip the time off from a Date object, by using Calendar. In Swift 4:
func stripTime(from originalDate: Date) -> Date {
let components = Calendar.current.dateComponents([.year, .month, .day], from: originalDate)
let date = Calendar.current.date(from: components)
return date!
}
Or as an extension:
extension Date {
func stripTime() -> Date {
let components = Calendar.current.dateComponents([.year, .month, .day], from: self)
let date = Calendar.current.date(from: components)
return date!
}
}
There is no date only class that's part of the Foundation framework.
This is a quick way to get a date only representation of an NSDate object:
let now = NSDate()
let dateFormatter = NSDateFormatter()
dateFormatter.timeStyle = NSDateFormatterStyle.NoStyle
dateFormatter.dateStyle = NSDateFormatterStyle.MediumStyle
print(dateFormatter.stringFromDate(now)) // Mar 3, 2016
NSDate's always have times because a date is a single point in time. If you're so inclined you can create a date without a time component but it usually defaults to 12AM:
let dateString = "2016-03-03"
let dateFromStringFormatter = NSDateFormatter()
dateFromStringFormatter.dateFormat = "yyyy-MM-dd"
let dateFromString = dateFromStringFormatter.dateFromString(dateString)
// dateFromString shows "Mar 3, 2016, 12:00 AM"
For Swift 3.0+
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
// optional
let date = dateFormatter.date(from: "2016-03-03") // Mar 3, 2015 at 12:00 AM
Swift 3.0
let date = Date()
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = DateFormatter.Style.none
dateFormatter.dateStyle = DateFormatter.Style.short
dateFormatter.string(from: date) // 12/15/16
If you want to get a Date object in Swift 4, like when you are trying to store a Date object in core data, you can use this method.
private func getDate() -> Date {
let today = Date()
let dateFormatter = DateFormatter()
dateFormatter.timeStyle = DateFormatter.Style.none
dateFormatter .dateStyle = DateFormatter.Style.short
let dateAsString = dateFormatter.string(from: today)
return dateFormatter.date(from: dateAsString)!
}
based on #John R Perry's answer.
There is no date only (no time) type in the Swift Standard library or Foundation (as of iOS 13).
Here is a type CalendarDate that you can use to represent a date as year, month, day in Swift:
Also available via Swift Package Manager here: CalendarDate
import Foundation
/**
CalendarDate is a Swift type that represents a Date as year, month and day value.
Includes support for formatting as a ISO 8601 string ('yyyy-mm-dd') and JSON coding.
*/
public struct CalendarDate: Equatable, Hashable {
public let year, month, day: Int
public static var today: CalendarDate {
CalendarDate(date: Date())
}
public init(year: Int, month: Int, day: Int) {
self.year = year
self.month = month
self.day = day
}
public init(date: Date) {
let calendar = Calendar.current
self.year = calendar.component(.year, from: date)
self.month = calendar.component(.month, from: date)
self.day = calendar.component(.day, from: date)
}
public var date: Date {
DateComponents(calendar: Calendar.current, year: self.year, month: self.month, day: self.day).date!
}
}
extension CalendarDate: LosslessStringConvertible {
public init?(_ description: String) {
if let date = Self.formatter.date(from: description) {
self.init(date: date)
} else {
return nil
}
}
public var description: String {
Self.formatter.string(from: self.date)
}
private static let formatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd"
return formatter
}()
}
extension CalendarDate: Codable {
public init(from decoder: Decoder) throws {
let container = try decoder.singleValueContainer()
let string = try container.decode(String.self)
guard let value = CalendarDate(string) else {
throw DecodingError.dataCorruptedError(
in: container,
debugDescription: "Not a valid calendar date: \"\(string)\""
)
}
self = value
}
public func encode(to encoder: Encoder) throws {
var container = encoder.singleValueContainer()
try container.encode(self.description)
}
}
I used a solution from this thread (which worked fine) and later found out that swift provides this:
Locale.current.calendar.startOfDay(for: Date()) // "Sep 10, 2022 at 12:00 AM"
It seems to do the same as the Date extension:
Date().stripTime() // "Sep 10, 2022 at 12:00 AM"
I would say that string of date value specified like "YYYY-MM-DD" + NSCalendar.Identifier could represent a date.
Having this you will be able to convert this date to any other calendar.
I know there are some good answers already.. just wanted to pass this one in here, which prints "true", so if you use the components or just set the time to 00:00:00 is basically the same...
let startComp = Calendar.current.dateComponents([.year, .month, .day], from: Date())
let first = Calendar.current.date(from: startComp)!
print(first == Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: Date()))
Hope this helps someone :)
As mentioned in other answers, there is no Date only type. If your goal is to display the current date which respects the locale from the user, this is the way to go:
//Returns 12/23/2022
DateFormatter.localizedString(from: Date.now, dateStyle: .short, timeStyle: .none)
//Returns 23 Dec 2022
DateFormatter.localizedString(from: Date.now, dateStyle: .medium, timeStyle: .none)

How to get Monday's date of the current week in swift

I'm trying to get Monday's date of the current week. This is treated as the first day of the week in my table view.
I also need to get Sunday's of the current week. This is treated as the last day of the week in my table view.
Current attempt:
let date = NSDate()
let calendar = NSCalendar.currentCalendar()
calendar.firstWeekday = 1
//attempt to changefirstday
let dateFormatter = NSDateFormatter()
let theDateFormat = NSDateFormatterStyle.ShortStyle
let theTimeFormat = NSDateFormatterStyle.ShortStyle
dateFormatter.dateStyle = theDateFormat
dateFormatter.timeStyle = theTimeFormat
let currentDateComponents = calendar.components([.YearForWeekOfYear, .WeekOfYear ], fromDate: date)
let startOfWeek = calendar.dateFromComponents(currentDateComponents)
print("startOfWeek is \(startOfWeek)")
let stringDate = dateFormatter.stringFromDate(startOfWeek!)
print("string date is \(stringDate)") //This is returning Sunday's date
I wrote Date extensions to get Date for certain weekday and here is how easy it is to use with Swift 5,
Date.today() // Oct 15, 2019 at 9:21 AM
Date.today().next(.monday) // Oct 21, 2019 at 9:21 AM
Date.today().next(.sunday) // Oct 20, 2019 at 9:21 AM
Date.today().previous(.sunday) // Oct 13, 2019 at 9:21 AM
Date.today().previous(.monday) // Oct 14, 2019 at 9:21 AM
Date.today().previous(.thursday) // Oct 10, 2019 at 9:21 AM
Date.today().next(.thursday) // Oct 17, 2019 at 9:21 AM
Date.today().previous(.thursday,
considerToday: true) // Oct 10, 2019 at 9:21 AM
Date.today().next(.monday)
.next(.sunday)
.next(.thursday) // Oct 31, 2019 at 9:21 AM
And here is Date extension for that,
extension Date {
static func today() -> Date {
return Date()
}
func next(_ weekday: Weekday, considerToday: Bool = false) -> Date {
return get(.next,
weekday,
considerToday: considerToday)
}
func previous(_ weekday: Weekday, considerToday: Bool = false) -> Date {
return get(.previous,
weekday,
considerToday: considerToday)
}
func get(_ direction: SearchDirection,
_ weekDay: Weekday,
considerToday consider: Bool = false) -> Date {
let dayName = weekDay.rawValue
let weekdaysName = getWeekDaysInEnglish().map { $0.lowercased() }
assert(weekdaysName.contains(dayName), "weekday symbol should be in form \(weekdaysName)")
let searchWeekdayIndex = weekdaysName.firstIndex(of: dayName)! + 1
let calendar = Calendar(identifier: .gregorian)
if consider && calendar.component(.weekday, from: self) == searchWeekdayIndex {
return self
}
var nextDateComponent = calendar.dateComponents([.hour, .minute, .second], from: self)
nextDateComponent.weekday = searchWeekdayIndex
let date = calendar.nextDate(after: self,
matching: nextDateComponent,
matchingPolicy: .nextTime,
direction: direction.calendarSearchDirection)
return date!
}
}
// MARK: Helper methods
extension Date {
func getWeekDaysInEnglish() -> [String] {
var calendar = Calendar(identifier: .gregorian)
calendar.locale = Locale(identifier: "en_US_POSIX")
return calendar.weekdaySymbols
}
enum Weekday: String {
case monday, tuesday, wednesday, thursday, friday, saturday, sunday
}
enum SearchDirection {
case next
case previous
var calendarSearchDirection: Calendar.SearchDirection {
switch self {
case .next:
return .forward
case .previous:
return .backward
}
}
}
}
You can use calendar ISO8601 where the first weekday is Monday:
Swift 5.2 or later
extension Calendar {
static let iso8601 = Calendar(identifier: .iso8601)
static let iso8601UTC: Calendar = {
var calendar = Calendar(identifier: .iso8601)
calendar.timeZone = TimeZone(identifier: "UTC")!
return calendar
}()
}
let monday =
Calendar.iso8601.dateComponents([.calendar, .yearForWeekOfYear, .weekOfYear], from: Date()).date! // "Nov 9, 2020 at 12:00 AM"
print(monday.description(with: .current)) // "Monday, November 9, 2020 at 12:00:00 AM Brasilia Standard Time\n"
let mondayUTC =
Calendar.iso8601UTC.dateComponents([.calendar, .yearForWeekOfYear, .weekOfYear], from: Date()).date! // "Nov 8, 2020 at 9:00 PM" TimeZone -03:00
print(mondayUTC) // "2020-11-09 00:00:00 +0000\n"
Implemented as a Date computer property extension:
extension Date {
var mondayOfTheSameWeek: Date {
Calendar.iso8601.dateComponents([.calendar, .yearForWeekOfYear, .weekOfYear], from: self).date!
}
var mondayOfTheSameWeekAtUTC: Date {
Calendar.iso8601UTC.dateComponents([.calendar, .yearForWeekOfYear, .weekOfYear], from: self).date!
}
}
let mondayOfTheSameWeek = Date().mondayOfTheSameWeek // "Nov 9, 2020 at 12:00 AM"
print(mondayOfTheSameWeek.description(with: .current)) // "Monday, November 9, 2020 at 12:00:00 AM Brasilia Standard Time\n"
let mondayOfTheSameWeekAtUTC = Date().mondayOfTheSameWeekAtUTC // "Nov 8, 2020 at 9:00 PM"
print(mondayOfTheSameWeekAtUTC) // "2020-11-09 00:00:00 +0000\n"
Here's a simplified version of Sandeep's answer.
Usage:
Date().next(.monday)
Date().next(.monday, considerToday: true)
Date().next(.monday, direction: .backward)
Extension:
public func next(_ weekday: Weekday,
direction: Calendar.SearchDirection = .forward,
considerToday: Bool = false) -> Date
{
let calendar = Calendar(identifier: .gregorian)
let components = DateComponents(weekday: weekday.rawValue)
if considerToday &&
calendar.component(.weekday, from: self) == weekday.rawValue
{
return self
}
return calendar.nextDate(after: self,
matching: components,
matchingPolicy: .nextTime,
direction: direction)!
}
public enum Weekday: Int {
case sunday = 1, monday, tuesday, wednesday, thursday, friday, saturday
}
Here is the extension I created, first it finds sunday and then it adds one day
extension Date {
var startOfWeek: Date? {
let gregorian = Calendar(identifier: .gregorian)
guard let sunday = gregorian.date(from: gregorian.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self)) else { return nil }
return gregorian.date(byAdding: .day, value: 1, to: sunday)
}
}
Try to use:
calendar.firstWeekday = 2
Edit
To be more specific: NSCalendar.currentCalendar() returns user calendar. According to docs:
The returned calendar is formed from the settings for the current user’s chosen system locale overlaid with any custom settings the user has specified in System Preferences.
If you want always Monday as first day, I think you should use:
let calendar = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
calendar!.firstWeekday = 2
Swift 4 Solution
I have figured out according to my requirement, where I have find out dates for following.
1. Today
2. Tomorrow
3. This Week
4. This Weekend
5. Next Week
6. Next Weekend
So, I have created Date Extension to get Dates of Current Week and Next Week.
CODE
extension Date {
func getWeekDates() -> (thisWeek:[Date],nextWeek:[Date]) {
var tuple: (thisWeek:[Date],nextWeek:[Date])
var arrThisWeek: [Date] = []
for i in 0..<7 {
arrThisWeek.append(Calendar.current.date(byAdding: .day, value: i, to: startOfWeek)!)
}
var arrNextWeek: [Date] = []
for i in 1...7 {
arrNextWeek.append(Calendar.current.date(byAdding: .day, value: i, to: arrThisWeek.last!)!)
}
tuple = (thisWeek: arrThisWeek,nextWeek: arrNextWeek)
return tuple
}
var tomorrow: Date {
return Calendar.current.date(byAdding: .day, value: 1, to: noon)!
}
var noon: Date {
return Calendar.current.date(bySettingHour: 12, minute: 0, second: 0, of: self)!
}
var startOfWeek: Date {
let gregorian = Calendar(identifier: .gregorian)
let sunday = gregorian.date(from: gregorian.dateComponents([.yearForWeekOfYear, .weekOfYear], from: self))
return gregorian.date(byAdding: .day, value: 1, to: sunday!)!
}
func toDate(format: String) -> String {
let formatter = DateFormatter()
formatter.dateFormat = format
return formatter.string(from: self)
}
}
USAGE:
let arrWeekDates = Date().getWeekDates() // Get dates of Current and Next week.
let dateFormat = "MMM dd" // Date format
let thisMon = arrWeekDates.thisWeek.first!.toDate(format: dateFormat)
let thisSat = arrWeekDates.thisWeek[arrWeekDates.thisWeek.count - 2].toDate(format: dateFormat)
let thisSun = arrWeekDates.thisWeek[arrWeekDates.thisWeek.count - 1].toDate(format: dateFormat)
let nextMon = arrWeekDates.nextWeek.first!.toDate(format: dateFormat)
let nextSat = arrWeekDates.nextWeek[arrWeekDates.nextWeek.count - 2].toDate(format: dateFormat)
let nextSun = arrWeekDates.nextWeek[arrWeekDates.nextWeek.count - 1].toDate(format: dateFormat)
print("Today: \(Date().toDate(format: dateFormat))") // Sep 26
print("Tomorrow: \(Date().tomorrow.toDate(format: dateFormat))") // Sep 27
print("This Week: \(thisMon) - \(thisSun)") // Sep 24 - Sep 30
print("This Weekend: \(thisSat) - \(thisSun)") // Sep 29 - Sep 30
print("Next Week: \(nextMon) - \(nextSun)") // Oct 01 - Oct 07
print("Next Weekend: \(nextSat) - \(nextSun)") // Oct 06 - Oct 07
You can modify Extension according to your need.
Thanks!
Addition to #Saneep answer
If you would like to get exact dateTime as per given/current date (lets say you wanted to convert Monday's dateTime -> 23-05-2016 12:00:00 to 23-05-2016 05:35:17) then try this:
func convertDate(date: NSDate, toGivendate: NSDate) -> NSDate {
let calendar = NSCalendar.currentCalendar()
let comp = calendar.components([.Year, .Month, .Day, .Hour, .Minute, .Second], fromDate: toGivendate)
let hour = comp.hour
let minute = comp.minute
let second = comp.second
let dateComp = calendar.components([.Year, .Month, .Day], fromDate: date)
let year = dateComp.year
let month = dateComp.month
let day = dateComp.day
let components = NSDateComponents()
components.year = year
components.month = month
components.day = day
components.hour = hour
components.minute = minute
components.second = second
let newConvertedDate = calendar.dateFromComponents(components)
return newConvertedDate!
}
simple code (remember to take better care of the optionals):
let now = Date()
var calendar = Calendar(identifier: .gregorian)
let timeZone = TimeZone(identifier: "UTC")!
let desiredWeekDay = 2
let weekDay = calendar.component(.weekday, from: now)
var weekDayDate = calendar.date(bySetting: .weekday, value: desiredWeekDay, of: now)!
/// Swift will give back the closest day matching the value above so we need to manipulate it to be always included at cuurent week.
if weekDayDate > now, weekDay > desiredWeekDay {
weekDayDate = weekDayDate - 7*24*60*60
}
print(weekDayDate)

Get just the date (no time) from UIDatePicker

I am trying to get just the date from UIDatePicker:
myDatePicker.datePickerMode = UIDatePicker.Mode.date
var selectedDate=myDatePicker.date
println(selectedDate)
However, this prints more than the date (it prints 2015-04-09 21:45:13 +0000). How do I get just the date part (without the time)? I also set the date picker Mode property to Date.
According to the Apple's documentation datePicker.mode should be date so you can use DateFormatter like so
Swift 4
datePicker.datePickerMode = UIDatePicker.Mode.date
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd MMMM yyyy"
let selectedDate = dateFormatter.string(from: datePicker.date)
print(selectedDate)
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "MM/dd/yy"
let dateString = dateFormatter.stringFromDate(myDatePicker.date)
You can print dateString, assign it to a label, whatever. The format will be
04/09/15
Swift 3/4, this will print a string of type Mar 08, 2017
datePicker.datePickerMode = .date
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "MMM dd, yyyy"
let selectedDate = dateFormatter.string(from: datePicker.date)
print(selectedDate)
I just want to add my bit in on here after coming across a similar problem. I would follow shades answer for String display of date. Not the from XCode 7 and swift 2 onwards when you use a UIDatePicker set the following to only view dates in the Picker:
#IBOutlet weak var datePicker: UIDatePicker!
datePicker.datePickerMode = .Date
Swift 4.0 version code is here
#IBAction func saveDateAction(_ sender: Any) {
myDatePicker.datePickerMode = UIDatePicker.Mode.date
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd MMM yyyy"
let selectedDate = dateFormatter.string(from: myDatePicker.date)
print("selectedDate",selectedDate)
}
Date picker date :
let date = datePicker.date
let dateConverted = Date.init(year: date.GetYear(), month: date.GetMonth(), day: date.GetDay())
//dateConverted result = 2019-02-27 00:00:00 +0000
let predicate = NSPredicate(format: "booking_date == %#", dateConverted as CVarArg)
Use this extensions:
extension Date {
init(year: Int, month: Int, day: Int) {
var dc = DateComponents()
dc.year = year
dc.month = month
dc.day = day
var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = TimeZone(secondsFromGMT: 0)!
if let date = calendar.date(from: dc) {
self.init(timeInterval: 0, since: date)
} else {
fatalError("Date component values were invalid.")
}
}
func GetYear() -> Int {
let calendar: NSCalendar! = NSCalendar(calendarIdentifier: .gregorian)
let components = calendar.components([.day , .month , .year], from: self)
return components.year!
}
func GetMonth() -> Int {
let calendar: NSCalendar! = NSCalendar(calendarIdentifier: .gregorian)
let components = calendar.components([.day , .month , .year], from: self)
return components.month!
}
func GetDay() -> Int {
let calendar: NSCalendar! = NSCalendar(calendarIdentifier: .gregorian)
let components = calendar.components([.day , .month , .year], from: self)
return components.day!
}
}