NSDateFormatter subtracting a day when removing time - swift

I am trying to remove time from date using NSDateFormatter. This is the code:
func dateWithOutTime( datDate: NSDate?) -> NSDate {
let formatter = NSDateFormatter()
formatter.dateFormat = "dd-MM-yyyy"
let stringDate: String = formatter.stringFromDate(datDate!)
let dateFromString = formatter.dateFromString(stringDate)
return dateFromString!
}
If i send in ex 04-01-2016 12:00:00, the return is 03-01-2016 23:00:00
I have tried changing the dateFormat, but it still keeps to subtracting a day from the date... Why? Please Help :)

The easiest way is to use startOfDayForDate of NSCalendar
Swift 2:
func dateWithOutTime( datDate: NSDate) -> NSDate {
return NSCalendar.currentCalendar().startOfDayForDate(datDate)
}
Swift 3+:
func dateWithOutTime(datDate: Date) -> Date {
return Calendar.current.startOfDay(for: datDate)
}
or to adjust the time zone to UTC/GMT
Swift 2:
func dateWithOutTime( datDate: NSDate) -> NSDate {
let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)!
calendar.timeZone = NSTimeZone(forSecondsFromGMT: 0)
return calendar.startOfDayForDate(datDate)
}
Swift 3+:
func dateWithOutTime(datDate: Date) -> Date {
var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = TimeZone(secondsFromGMT: 0)!
return calendar.startOfDay(for: datDate)
}

Two things:
(a) This can be done without using NSDateFormatter. (b) Calling print(aDate) will give you the UTC time, not in your local time. After losing too many brain cells trying to mentally convert back and forth, I decided to make an extension to NSDate to print it in my local timezone.
// NSDateFormatter is expensive to create. Create it once and reuse
let dateFormatter = NSDateFormatter()
dateFormatter.locale = NSLocale.currentLocale()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZZ"
extension NSDate {
// This will print the date in the local timezone
var localTime: String {
return dateFormatter.stringFromDate(self)
}
}
func dateWithOutTime(datDate: NSDate?) -> NSDate {
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Year, .Month, .Day], fromDate: datDate!)
return calendar.dateFromComponents(components)!
}
let datDate = NSCalendar.currentCalendar().dateWithEra(1, year: 2016, month: 1, day: 4, hour: 12, minute: 0, second: 0, nanosecond: 0)
let result = dateWithOutTime(datDate)
print(result.localTime)

Related

Date from String in Swift but it becomes the previous day

I am trying to create a day from a string (mSince) :
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let newDate = dateFormatter.date(from:mSince as! String)!
and the print values are:
mSince = Optional(2021-04-25)
newDate = 2021-04-24 21:00:00 +0000
I could not figure out why newDate becomes the previous day.
Thank you!
Below is an example of how to create dates from multiple UTC timezones and an example of how to get the delta (in seconds) between the dates:
extension Date {
static func - (lhs: Date, rhs: Date) -> TimeInterval {
return lhs.timeIntervalSinceReferenceDate - rhs.timeIntervalSinceReferenceDate
}
}
let utcDateFormatter = DateFormatter()
utcDateFormatter.dateStyle = .medium
utcDateFormatter.timeStyle = .medium
// Set the timeZone to the device’s local time zone.
utcDateFormatter.timeZone = TimeZone(abbreviation: "UTC")
let date1 = Date()
print(utcDateFormatter.string(from: date1))
// Parsing a string date
let dateString1 = "May 11, 2020 at 4:23:11 AM"
let utcDate1 = utcDateFormatter.date(from: dateString1)
// Set a date for a different timeZone (2 hours difference)
utcDateFormatter.timeZone = TimeZone(secondsFromGMT: 3600)
// Printing a Date
let date2 = Date()
print(utcDateFormatter.string(from: date2))
// Parsing a string representing a date
let dateString2 = "May 11, 2020 at 4:23:11 AM"
let utcDate2 = utcDateFormatter.date(from: dateString2)
let diff = utcDate1! - utcDate2!
print(diff)

Incorrect time in Date from 12-Hr format Time String - Swift

I have following strings as 12-Hr format time:
let timeFrom = "05:30 AM";
let timeTo = "04:35 PM";
And trying to get date from these for comparison as follows:
let openTime = timeFrom.date(format: "hh:mm a")
let closeTime = timeTo.date(format: "hh:mm a")
With this extension :
extension String
{
func date(format:String) -> Date?
{
let formatter = DateFormatter()
formatter.dateFormat = format
formatter.timeZone = NSTimeZone.local
return formatter .date(from: self)
}
}
When I print openTime and closeTime, I'm getting incorrect values in time:
print(openTime) // 2000-01-01 00:00:00 +0000
print(closeTime) // 2000-01-01 11:00:00 +0000
Why this is so ? I think it is smoething related to time zone, so I visit NSDateFormatter return wrong date + Swift, but nothing worked for me. If anybody have the solution, please help me. Thank you !
I check with swift 3 and Xcode 8 with small changes its working please check
let timeFrom = "05:30 AM";
let timeTo = "04:35 PM";
let openTime = timeFrom.date(format: "hh:mm a")
let closeTime = timeTo.date(format: "hh:mm a")
print(openTime)
print(closeTime)
and make change in extension
extension String{
func date(format:String) -> Date?
{
let formatter = DateFormatter()
formatter.timeZone = TimeZone(abbreviation: "GMT+0:00")
formatter.dateFormat = format
//formatter.timeZone = TimeZone.current //or autoupdatingCurrent
return formatter .date(from: self)
}}

How can I figure out the day difference in the following example

I am calculating the day difference between two dates, but I figured out the the following code is actually giving me the difference for 24 hours rather than the difference in date. I have the following code:
func daysBetweenDate(startDate: NSDate, endDate: NSDate) -> Int
{
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Day], fromDate:startDate, toDate: endDate, options: [])
return components.day
}
So, for the following example I get this result:
lastLaunch:2016-06-10 01:39:07 +0000
toady: 2016-06-11 00:41:41 +0000
dayDiff:0
I would have expected the day difference to be one, since last launch was on the 10th and today is the 11th. How can I change the code to give me the actual difference in date for days?
You can use Calendar method date BySettingHour to get the noon time for your startDate and endDate, to make your calendar calculations not time sensitive:
Xcode 8.2.1 • Swift 3.0.2
extension Date {
var noon: Date? {
return Calendar.autoupdatingCurrent.date(bySettingHour: 12, minute: 0, second: 0, of: self)
}
func daysBetween(_ date: Date) -> Int? {
guard let noon = noon, let date = date.noon else { return nil }
return Calendar.autoupdatingCurrent.dateComponents([.day], from: noon, to: date).day
}
}
let startDateString = "2016-06-10 01:39:07 +0000"
let todayString = "2016-06-11 00:41:41 +0000"
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale(identifier: "ex_US_POSIX")
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss xxxx"
if let startDate = formatter.date(from: startDateString),
let endDate = formatter.date(from: todayString),
let days = startDate.daysBetween(endDate) {
print(startDate) // "2016-06-10 01:39:07 +0000\n"
print(endDate) // "2016-06-11 00:41:41 +0000\n"
print(days ?? "nil") // 1
}
Swift 2.x
extension NSDate {
var noon: NSDate {
return NSCalendar.currentCalendar().dateBySettingHour(12, minute: 0, second: 0, ofDate: self, options: [])!
}
}
func daysBetweenDate(startDate: NSDate, endDate: NSDate) -> Int {
return NSCalendar.currentCalendar().components([.Day],
fromDate: startDate.noon,
toDate: endDate.noon,
options: []).day
}

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)

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!
}
}