Here is my DateFormatter Code
let formatter = DateFormatter()
formatter.dateFormat = "MMM dd"
let dateString = formatter.string(from: date)
Now:
po dateString
gives the result "May 18"
po date gives the result 2021-05-17 18:30:00 +0000
This does not make sense to me - why is the Date May 17 2021 being converted to the String May 18?
A Date object records an instant in time anywhere on the planet.
That instant in time will be on a different calendar day (day/month/year) depending on what time zone you are in.
By default, date formatters work in the device's current time zone.
When you log a Date using po date or print(date) the default description of a Date displays that date in UTC using the ISO 8601 date format. Depending on the user's time zone, the Date in UTC might be on a different calendar day than it is in the local time zone
If you want to log a date in the user's local time zone, use po date.description(with: Locale.current) or po DateFormatter.localizedString(from: date, dateStyle: .medium, timeStyle: .medium)
This depends on the current time zone of the formatter used , for 0 based use
formatter.timeZone = TimeZone(abbreviation: "UTC")
Related
I'm using FSCalendar in a Swift app, and when user selects a day, I'm printing the selected day, and the it prints the previous day, at 23:00. I'm not sure why and how can I solve this. I'm in spain. Maybe it's related with where you are and your local hour?
This is how I'm printing the selected day:
extension CalendarDataViewViewController: FSCalendarDataSource {
func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd hh:mm:ss"
let now = df.string(from: date)
logger.debug("Date: \(date)")
}
}
And this is what it's printed when I select 18 march:
21:01:24.646 💚 DEBUG CalendarDataViewViewController.calendar():258 - Date: 2021-03-17 23:00:00 +0000
Your code creates a date formatter, converts the returned date to a date string with that formatter, and then ignores that and simply prints the date, which is being displayed in UTC. (Note the output Date: 2021-03-17 23:00:00 +0000)
Change your log command to read:
logger.debug("Date: \(now)")
And by the way, the variable name now is a terrible choice for holding a user-selected date that is not the current date.
I'd suggest renaming the returned date parameter selectedDate and the String output of the formatter as selectedDateString
Edit:
Consider this code:
import Foundation
func dateStringFromDate(_ inputDate: Date) -> String {
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd hh:mm:ss a"
let dateString = df.string(from: inputDate)
return dateString
}
func isoDateStringFromDate(_ inputDate: Date) -> String {
let df = ISO8601DateFormatter()
df.formatOptions = .withInternetDateTime
df.timeZone = TimeZone.current //Force the formatter to express the time in the current time zone, including offset
let dateString = df.string(from: inputDate)
return dateString
}
let now = Date()
print("Current timezone = \(TimeZone.current)")
print("now in 'raw' format = \(now)")
let localizedDateString = DateFormatter.localizedString(from: now,
dateStyle: .medium,
timeStyle: .medium)
print("localizedString for the current date = \(localizedDateString)")
print("dateStringFromDate = \(dateStringFromDate(now))")
print("isoDateStringFromDate = \(isoDateStringFromDate(now))")
Right now, at about 9:16 PM EDT on Thursday March 18th, that logs the following:
Current timezone = America/New_York (current)
now in 'raw' format = 2021-03-19 01:16:52 +0000
localizedString for the current date = Mar 18, 2021 at 9:16:52 PM
dateStringFromDate = 2021-03-18 09:16:52 PM
isoDateStringFromDate = 2021-03-18T21:16:52-04:00
The 'raw' date format is in GMT, with an offset value of 0. In that form, in GMT, the calendar date is already March 19th. (Because GMT is 4 hours ahead of EDT)
The class function NSDateFormatter.localizedString(from:dateStyle:timeStyle) displays a date in the current time zone and using the device's locale settings. The dateStyle and timeStyle parameters give you the option to choose whether or not, and in what format (short, medium, or long) to display the date or time.
An ISO8601DateFormatter displays the date following the conventions in the ISO8601 standard. The isoDateStringFromDate(:) function above uses the .withInternetDateTime option to express the date in the ISO8601 "internet date and time" format. I forced that date to be in the local time zone, so it displays the date with a -4 hour offset from GMT (since it is EDT, eastern daylight savings time where I live.)
The function dateStringFromDate(_:) is a slight variation on your function. It returns a date string in the current time zone, using 12 hour times and an AM/PM string.
I am struggling with Date and I'm assuming is TimeZone.
Currently I get from my backend a string like this "2020-04-07" and when I try to convert it to date it turns into 2020-04-06 22:00:00 +0000. I am in Spain (UTC+2) which I guess this is why it removes 2 hours?
This is my date formatter:
var dateFormatter: DateFormatter = {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
dateFormatter.timeZone = TimeZone.current
return dateFormatter
}()
And I call it dateFormatter.date(from: startDateString)
I am setting my current timezone but seems to be ignoring it or am I missing something?
I have followed a lot of answers from here but it's always the same result.
Thank you
The Date object does not have any inherent locale / time zone. It just represents a moment in time. If you want to see that Date as a string in a specific locale/time zone you have to use a date formatter. Or there's descriptionWithLocale. If you use print it will print a debug description of the Date instance in UTC.
I want to return a date/time coming from my API. Server is based in Amsterdam.
Swift:
//load from api
print(date)
let df = DateFormatter()
df.dateFormat = "yyyy-MM-dd HH:mm:ss"
df.timeZone = TimeZone(identifier: "Europe/Amsterdam")
df.locale = Locale(identifier: "en_US")
var updated = dateFormatter.date(from: "\(date)")
//return format
print(updated)
Return:
2020-01-10 00:01:01
Optional(2020-01-09 23:01:01 +0000)
I don't know why, but the output is returning GMT I think. To output should be 2020-01-10 00:01:01 +0000 because Amsterdam is GMT+1.
As vadian explained in the comments it's working as it supposed to.
However, if you want to display a local date instead of UTC, you can use my snippet here.
If know you will always want just one given time zone just modify the code to add the correct amount of seconds.
(In the case of Amsterdam time it's +3600 seconds to UTC for example.)
I have a date from a UIControl. I get date as string such as 06-12-2016 01:25 PM. Now I want to convert it into a format as 2016-12-06 13:25:00 I have tried below code t do so but it just gives me wrong date for ex. 2016-12-06 18:55:00. I have used below code for this:
func converStingToDate(str_date:String)->String
{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy H:mm a"
let date = dateFormatter.date(from: str_date)
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
return dateFormatter.string(from: date!)
}
Please suggest me a better code. Also if you guys can help me to understand all this date formatting concept how it is done ?
The code is correct and the date is correct (although you should use h for 12-hour hour).
Your time zone is UTC+0530 and print() displays the date in UTC.
If you need to print the correct local time set the time zone of the formatter to UTC:
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")`
I need to store Date variable in CoreData in iOS
I need to store the Date only without the Time, So I made a formatter that discard the time partition from the NSDate variable.
But I have a strange result:
This is my code:
let dateStr = "2016-02-14 11:27:01"
let df2 = NSDateFormatter()
df2.timeZone = NSTimeZone.defaultTimeZone()
df2.dateFormat = "yyyy-MM-dd HH:mm:ss"
print(dateStr)
if let date = df2.dateFromString(dateStr) {
df2.dateFormat = "yyyy-MM-dd"
print("-> \(df2.dateFromString(df2.stringFromDate(date)))")
}
and this is the output:
2016-02-14 11:27:01
-> Optional(2016-02-13 20:00:00 +0000)
Why does the formatter decrease the day by one ?
I tried many dates with same issue
Your time zone is obviously UTC+4.
To get UTC set the time zone accordingly.
df2.timeZone = NSTimeZone(forSecondsFromGMT: 0)
But although you see a date 4 hours ago the NSDate object is treated correctly depending on your time zone. The print command displays always UTC ignoring the time zone information, because NSDate is just a wrapper for a Double number.