This is a piece of code that was working in earlier version of swift. It is now giving an error (Cannot convert value of type 'NSDate' to type 'NSDate.Date' in coercion)
extension NSDate {
struct Date {
static let formatterISO8601: DateFormatter = {
let formatter = DateFormatter()
formatter.calendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.ISO8601)! as Calendar
formatter.locale = NSLocale.current
formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0) as TimeZone!
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXX"
return formatter
}()
}
var formattedISO8601: String { return Date.formatterISO8601.string(from: self as Date) }
}
Issue is that in Swift 3 there is already a structure define with named Date.
So what you can do is change your struct name to MyDate or something else and you all set to go.
Also it is better if you use new Date, Calendar and TimeZone instead of NSDate, NSCalendar and NSTimeZone.
Or make extension of Date like this way.
extension Date {
static let formatterISO8601: DateFormatter = {
let formatter = DateFormatter()
formatter.calendar = Calendar(identifier: .iso8601)
formatter.locale = Locale.current
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXX"
return formatter
}()
var formattedISO8601: String { return Date.formatterISO8601.string(from: self) }
}
Extensions for both NSDate and Date.
extension Date {
static let formatterISO8601: DateFormatter = {
let formatter = DateFormatter()
formatter.calendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.ISO8601)! as Calendar
formatter.locale = NSLocale.current
formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0) as TimeZone!
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXX"
return formatter
}()
func formattedISO8601() -> String {
return Date.formatterISO8601.string(from: self)
}
}
extension NSDate {
func formattedISO8601() -> String {
return Date.formatterISO8601.string(from: self as Date)
}
}
And use it like this ...
// NSDate
let nsdate = NSDate.init()
let formattedDate = nsdate.formattedISO8601()
// Date
let date = Date.init()
let formattedNsDate = date.formattedISO8601()
try this
extension Date {
static let formatterISO8601: DateFormatter = {
let formatter = DateFormatter()
formatter.calendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.ISO8601)! as Calendar
formatter.locale = NSLocale.current
formatter.timeZone = NSTimeZone(forSecondsFromGMT: 0) as TimeZone!
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssXXX"
return formatter
}()
var formattedISO8601: String { return Date.formatterISO8601.string(from: self)
}
}
Related
I need to return date string is same format I retrieve it, but after converting to Date and back it lose few characters
var dateStr = "2019-08-02T11:46:46.5117312Z"
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.SSSZZZZZ"
let date = formatter.date(from: dateStr)
var str = formatter.string(from: date!) // ===>>> "2019-08-02T11:46:46.511Z"
You can do it with custom formatter. But note that there not enough Double precision to store date. Result is 2019-08-02T11:46:46.5117311Z. Code:
class CustomDateFormatter {
private let dateFormatter: DateFormatter = {
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"
return formatter
}()
func date(fromString str: String) -> Date? {
let strs = str.components(separatedBy: CharacterSet(charactersIn: ".Z"))
if strs.count != 3 {
return nil
}
let dateStr = strs[0]
let secondsStr = strs[1]
guard let date = dateFormatter.date(from: dateStr),
let seconds = Double("0."+secondsStr) else {
return nil
}
let timeinteval = date.timeIntervalSince1970 + seconds
return Date(timeIntervalSince1970: timeinteval)
}
func string(fromDate date: Date) -> String {
let clippedDate = Date(timeIntervalSince1970: floor(date.timeIntervalSince1970))
let seconds = date.timeIntervalSince1970.truncatingRemainder(dividingBy: 1)
var lastPart = String(format: "%.7f", seconds)
lastPart = (lastPart as NSString).substring(from: 1)
return "\(dateFormatter.string(from: clippedDate))\(lastPart)Z"
}
}
let dateStr = "2019-08-02T11:46:46.5117312Z"
let formatter = CustomDateFormatter()
let date = formatter.date(fromString: dateStr)!
print(formatter.string(fromDate: date)) // =====>> 2019-08-02T11:46:46.5117311Z
I want to get the time in 12h or 24h format from DateFormatter according to option "24-Hour-Time" in User Preferences.
If I set "24-Hour-Time" = "on" and DateFormatter like this:
let formatter = DateFormatter()
let locale = Locale(identifier: "en_US")
print(locale) // "en_US (fixed)\n"
formatter.locale = locale
formatter.dateStyle = .none
formatter.timeStyle = .short
formatter.string(from: Date()) // "2:54 PM" (not "14:54")
But if I set:
let locale = Locale.current // "en_US (current)\n"
instead of
let locale = Locale(identifier: "en_US") // "en_US (fixed)\n"
the result will be
formatter.string(from: Date()) // "14:54"
How to create custom locale setting 12 or 24 hour format.
//MARK:- use this to convert 24 hours time format to 12 hour Formate String
func TwelveHourFormateFrom24Hours(time : String)->String
{
let Time = time.components(separatedBy: ".")
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "H:mm:ss"
if let inDate = dateFormatter.date(from: Time[0])
{
dateFormatter.dateFormat = "h:mm a"
dateFormatter.timeZone = TimeZone.current
let outTime = dateFormatter.string(from: inDate)
print("in \(time)")
print("out \(outTime)")
return outTime
}
return time
}
//MARK:- 24 hour Formate String
func TwentyFourHourFormate(time : String)->String
{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "h:mm a"
if let inDate = dateFormatter.date(from: time)
{
dateFormatter.dateFormat = "H:mm:ss.sss"
let outTime = dateFormatter.string(from: inDate)
print("in \(time)")
print("out \(outTime)")
return outTime
}
return time
}
This question already has answers here:
Convert NSDate to NSString
(19 answers)
Closed 5 years ago.
I am trying to convert a NSDate to a String and then Change Format. But when I pass NSDate to String it is producing whitespace.
let formatter = DateFormatter()
let myString = (String(describing: date))
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let yourDate: Date? = formatter.date(from: myString)
formatter.dateFormat = "dd-MMM-yyyy"
print(yourDate)
you get the detail information from Apple Dateformatter Document.If you want to set the dateformat for your dateString, see this link , the detail dateformat you can get here
for e.g , do like
let formatter = DateFormatter()
// initially set the format based on your datepicker date / server String
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let myString = formatter.string(from: Date()) // string purpose I add here
// convert your string to date
let yourDate = formatter.date(from: myString)
//then again set the date format whhich type of output you need
formatter.dateFormat = "dd-MMM-yyyy"
// again convert your date to string
let myStringDate = formatter.string(from: yourDate!)
print(myStringDate)
you get the output as
I always use this code while converting Date to String . (Swift 3)
extension Date
{
func toString( dateFormat format : String ) -> String
{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = format
return dateFormatter.string(from: self)
}
}
and call like this . .
let today = Date()
today.toString(dateFormat: "dd-MM")
DateFormatter has some factory date styles for those too lazy to tinker with formatting strings. If you don't need a custom style, here's another option:
extension Date {
func asString(style: DateFormatter.Style) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = style
return dateFormatter.string(from: self)
}
}
This gives you the following styles:
short, medium, long, full
Example usage:
let myDate = Date()
myDate.asString(style: .full) // Wednesday, January 10, 2018
myDate.asString(style: .long) // January 10, 2018
myDate.asString(style: .medium) // Jan 10, 2018
myDate.asString(style: .short) // 1/10/18
Your updated code.update it.
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let myString = formatter.string(from: date as Date)
let yourDate: Date? = formatter.date(from: myString)
formatter.dateFormat = "dd-MMM-yyyy"
print(yourDate!)
Something to keep in mind when creating formatters is to try to reuse the same instance if you can, as formatters are fairly computationally expensive to create. The following is a pattern I frequently use for apps where I can share the same formatter app-wide, adapted from NSHipster.
extension DateFormatter {
static var sharedDateFormatter: DateFormatter = {
let dateFormatter = DateFormatter()
// Add your formatter configuration here
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
return dateFormatter
}()
}
Usage:
let dateString = DateFormatter.sharedDateFormatter.string(from: Date())
After allocating DateFormatter you need to give the formatted string
then you can convert as string like this way
var date = Date()
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let myString = formatter.string(from: date)
let yourDate: Date? = formatter.date(from: myString)
formatter.dateFormat = "dd-MMM-yyyy"
let updatedString = formatter.string(from: yourDate!)
print(updatedString)
OutPut
01-Mar-2017
You can use this extension:
extension Date {
func toString(withFormat format: String) -> String {
let formatter = DateFormatter()
formatter.dateFormat = format
let myString = formatter.string(from: self)
let yourDate = formatter.date(from: myString)
formatter.dateFormat = format
return formatter.string(from: yourDate!)
}
}
And use it in your view controller like this (replace <"yyyy"> with your format):
yourString = yourDate.toString(withFormat: "yyyy")
I want to get my Date in DD.MM.YYYY HH:mm:ss as a String.
I use the following extension:
extension Date {
var localTime: String {
return description(with: Locale.current)
}
}
and the following code when my datePicker changes:
#IBAction func datePickerChanged(_ sender: UIDatePicker) {
dateLabel.text = datePicker.date.localTime
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy hh:mm"
let TestDateTime = formatter.date(from: datePicker.date.localTime)
}
What am I doing wrong?
Your code is completely wrong. Just do the following:
#IBAction func datePickerChanged(_ sender: UIDatePicker) {
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy HH:mm"
dateLabel.text = formatter.string(from: sender.date)
}
This will convert the date picker's chosen date to a string in the format dd.MM.yyyy HH:mm in local time.
Never use the description method to convert any object to a user presented value.
Just used the function in your code(swift 4.2).
public func convertDateFormatter(date: String) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"//this your string date format
dateFormatter.timeZone = NSTimeZone(name: "UTC") as TimeZone!
dateFormatter.locale = Locale(identifier: "your_loc_id")
let convertedDate = dateFormatter.date(from: date)
guard dateFormatter.date(from: date) != nil else {
assert(false, "no date from string")
return ""
}
dateFormatter.dateFormat = "HH:mm a"///this is what you want to convert format
dateFormatter.timeZone = NSTimeZone(name: "UTC") as TimeZone!
let timeStamp = dateFormatter.string(from: convertedDate!)
print(timeStamp)
return timeStamp
}
Thanks
I have a UIDatePicker that is connected to a UILabel. I want the user to pick a birthday that is more than 18 years ago (age restriction). So I have this line to set the maximumDate value:
datePicker.maximumDate = NSCalendar.currentCalendar().dateByAddingUnit(.Year, value: -18, toDate: NSDate(), options: [])
This line however causes the picker to show a 1 day behind the selected date. for example if I choose September 27, 1956 on the picker the label shows September 26, 1956 I believe it has to do with NSDate() using a different timezone one that is behind my local timezone.
switch dequeueFrom[indexPath.row] {
case .Birthday:
if let pickedBday = pickedBday,
let bday = NSDate.dateFromISOString(pickedBday) {
(cell as! RegisterTextFieldCell).content(bday.longFormattedString())
}
// dateFromISOSString is declared in an extension.swift
class func dateFromComponents(components: NSDateComponents) -> NSDate? {
let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)
return calendar?.dateFromComponents(components)
}
class func dateFromString(string: String) -> NSDate? {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss-SSS"
if let stringDate = dateFormatter.dateFromString(string) {
return stringDate
} else {
return nil
}
}
func ISOStringFromDate() -> String {
let dateFormatter = NSDateFormatter()
dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"
return dateFormatter.stringFromDate(self).stringByAppendingString("Z")
}
class func dateFromISOString(string: String) -> NSDate? {
let dateFormatter = NSDateFormatter()
dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
if let stringDate = dateFormatter.dateFromString(string) {
return stringDate
} else {
return nil
}
}
Any help with how I can make NSDate() be my local timezone so this one day behind issue can go away? Any help is greatly appreciated :)
The problem is in your method ISOStringFromDate because you are getting the local time and manually adding the Z (Z means UTC) to the string. Try like this when creating your iso8601:
extension NSDate {
var iso8601: String {
let dateFormatter = NSDateFormatter()
dateFormatter.locale = NSLocale(localeIdentifier: "en_US_POSIX")
dateFormatter.timeZone = NSTimeZone(forSecondsFromGMT: 0)
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
return dateFormatter.stringFromDate(self)
}
}
and your code should be:
pickedDate.iso8601 // to get your date iso8601 string