Take a certain amount of days off the current date and print with certain date format - swift

How would I take a certain amount of days (take away one day) off the current date and print with certain date format to the console.
I'm currently using:
print((Calendar.current as NSCalendar).date(byAdding: .day, value: -1, to: Date(), options: [])!)
Which prints the date and time as:
yyyy-MM-dd HH:MM:SS +0000
But I want it to print like:
dd-MM-yyyy
Is this at all possible?

It's best to break that into a few more easily readable/maintainable lines. First, calculate the date you want, then apply a date formatter.
let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: Date())
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy"
print(dateFormatter.stringFromDate(yesterday))

swift 3.0 version
let yesterday = Calendar.current.date(byAdding: .day, value: -1, to: Date())
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd-MM-yyyy"
if let yesterday = yesterday {
print(dateFormatter.string(from: yesterday))
}else{
print("Date incorrectly manipulated")
}

You shouldn't use fixed format for Date format strings. Because you might have users from around the world and they don't see dates in the same way.
Rather you should use template format. You just specify which components you want to show and their order like:
let dateFormatter = DateFormatter()
// dateFormatter.locale = Locale(identifier: "bn-BD") // Enable this line only at the time of your debugging/testing
dateFormatter.dateFormat = DateFormatter.dateFormat(fromTemplate: "ddMMyyyy",
options: 0,
locale: dateFormatter.locale)
let date = Calendar.current.date(byAdding: .day, value: -1, to: Date())
if let date = date {
let dateString = dateFormatter.string(from: date)
print(dateString)
}
You shouldn't set your locale by yourself. It's done by the
framework. You should only set your locale manually only at the time
of testing your app.
In the above example I'm using Locale as "bn-BD" which means Bangla in Bangladesh. You can find your a list of locales here

Related

EST date timezone doesn't add up hours properly swift 5

I am trying to add up to 2 hours to the current time. When it's "Asia/Kolkata" the following function works, but if it's "America/Toronto" it reduces the time by 2 hours instead of adding. Please see the below code and shade some light where I am wrong. TIA
let now = Date().localDate() // 2021-03-16 06:24:44 +0000 //extension of localDate
let modifiedDate = Calendar.current.date(byAdding: .hour, value: 2, to: now)!
let hour = Calendar.current.dateComponents([.hour], from: modifiedDate, to: now).hour //-2
let formatter = DateFormatter()
let timezone = TimeZone.current.identifier
formatter.timeZone = TimeZone(abbreviation: "America/Toronto")
formatter.locale = Calendar.current.locale
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss ZZZ"
self.dateString = formatter.string(from: modifiedDate)
print("Date: ", self.dateString) //2021-03-16 04:24:44 -0400
extension Date {
func localDate() -> Date {
let nowUTC = Date()
let timeZoneOffset = Double(TimeZone.current.secondsFromGMT(for: nowUTC))
guard let localDate = Calendar.current.date(byAdding: .second, value: Int(timeZoneOffset), to: nowUTC) else {return Date()}
return localDate
}
}
Your extension is totally wrong. There is no "nowUTC". Now is anywhere in the world. A date has no timezone it is just a point in time. You should never add/subtract the seconds from GMT to your Date() / now object
To make it easier to explain what is wrong there all you need is to use Date method description with locale and use current. Note also that adding seconds to a date will never fail so it is safe to safely force unwrap the result. The use of a guard there is pointless and don't return Date() when failing. You should change the return type to an optional Date and return nil but it is not necessary in this case:
Again the following extension is what you should never do
extension Date {
func localDate() -> Date {
let nowUTC = Date()
let timeZoneOffset = Double(TimeZone.current.secondsFromGMT(for: nowUTC))
return Calendar.current.date(byAdding: .second, value: Int(timeZoneOffset), to: nowUTC)!
}
}
Now it is 13:06 in Rio de Janeiro Brazil and your date returned by the localDate method is "Tuesday, March 16, 2021 at 10:06:13 AM Brasilia Standard Time"
Date().localDate().description(with: .current) // Tuesday, March 16, 2021 at 10:06:13 AM Brasilia Standard Time"
If you need "local date" all you need is to use Date(). If you would like to display the local date you need to use DateFormatter. When you print the date object it will always show the UTC time (+0000). If you want to print the local date just print the description with the current locale.
let now = Date()
now.description(with: .current) // "Tuesday, March 16, 2021 at 1:06:13 PM Brasilia Standard Time"

Swift - date formatter returns unwanted time

If I convert "2019-01-01T00:00:00+0000" to a date, I would like the date to be the date in the string - January 1, 2019. And if I calculate the number of seconds in the time portion, I would like the result to be zero.
The problem is, when I convert my string into a date, it is stored in the UTC timezone. My locale is set to "en_US_POSIX", and my time zone is set to current. My date formatter uses "yyyy-MM-dd'T'HH:mm:ssZ". I know that the final Z means UTC, but I can't seem to figure out the correct field symbol to get the results I want.
func convertToDate(_ dateString: String) -> Date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.timeZone = .current
let date = dateFormatter.date(from: dateString)
else {
print("DATE ERROR:", dateString)
return Date()
}
return date
}
If you know for sure that the date strings you wish to parse will always end with a timezone in the form +XXXX then you can trim off that timezone from the string and then parse the remaining string as local time.
func convertToDate(_ dateString: String) -> Date? {
let minusTZ = String(dateString.dropLast(5)) // Assume the string ends with a +9999 timezone
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss"
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
let date = dateFormatter.date(from: minusTZ)
return date
}
This will give you a local date with the same date and time in the original string regardless of the timezone of the original string.

Joining separated Date and Hour to create a single Date() Object

I have this app written in swift where I get a future date and a future hour (As Unix Timestamp) separately and I want to turned them into one Date() Object so I can converted to Unix Timestamp.
If you now another way to converted directly to Unix Timestamp feel free to post.
This may give you some ideas on how to accomplish what you want:
let calendar = Calendar.current
let currentDate = Date()
// Random future date, 1 month from now
let futureDate = calendar.date(byAdding: .month, value: 1, to: currentDate)!
let futureDateComponents = calendar.dateComponents([.year, .month, .day], from: futureDate)
// Random hour
let futureHour = 2
// Use your future date and your future hour to set the components for the new date to be created
var newDateComponents = calendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: currentDate)
newDateComponents.year = futureDateComponents.year
newDateComponents.month = futureDateComponents.month
newDateComponents.day = futureDateComponents.day
newDateComponents.hour = futureHour
newDateComponents.minute = 0
newDateComponents.second = 0
// Create a new date from components
let newDate = calendar.date(from: newDateComponents)!
// Convert new date to unix time format
let unixTime = newDate.timeIntervalSince1970
print(newDate) // 2018-03-06 02:00:00 +0000
print(unixTime) // 1520301600.0
Note that in a real project you should avoid force unwrapping (i.e. using '!').
If you have a date string in the form of dd-MM-yyyy, you can convert that to a Date object like so:
let string = "02-06-2018"
let formatter = DateFormatter()
formatter.dateFormat = "dd-MM-yyyy"
formatter.locale = Locale(identifier: "en_US_POSIX") // this is only needed if string is always gregorian but you don't know what locale the device is using
guard let date = formatter.date(from: string) else {
// handle error however you'd like
return
}
Or, if you already have a Date object, then you don't need the above. But regardless, once you have a Date, you can then get a Date by setting the hour, minute, and second as follows:
let hour = 14 // 2pm
guard let result = Calendar.current.date(bySettingHour: hour, minute: 0, second: 0, of: date) else {
// handle error however you'd like
return
}

Why does Date formatter returns date correctly but time is showing as 00:00:00 when converting string to NSDate

I have a function where i have to retrieve a date from my own sqlite db of app. I have saved it using the formatter
My work flow
1..Save a date to db on Application did enter background(Saved as String)
2..When application become foreground again i make a date instance at that point of time too. Now i have two date's.
3..Convert both dates to correct format and get the seconds difference.
Convert from date to String-->
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.Z"
let myString = formatter.stringFromDate(NSDate()) // i get value"2017-05-18 16:49:38.+0530"
But when i reconvert it to NSDate(I Mean when i convert this to string again)-->
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd HH:mm:ss.Z"
let lastloginDate=formatter.dateFromString(lastLogin) // i get value(Converting back to string \n for checking as the time difference was zero ) 2017-05-18 00:00:00.+0530
I want to compare two dates like a session out service , I do this by getting the calendar components difference of minute. However since its coming like this, the difference his always zero .
let myString1 = formatter.stringFromDate(date1)
let myString2 = formatter.stringFromDate(date2)
print("DATE 1\(myString1) DATE 2 \(myString2)")
let components = calendar.components(flags, fromDate: date2, toDate: date1, options: [])
let diff = components.second
print("Diffrence is \(diff)") // Always zero 😱
Why is this?
Try this one.
let myString1 = formatter.stringFromDate(date1)
let myString2 = formatter.stringFromDate(date2)
print("DATE 1\(myString1) DATE 2 \(myString2)")
let components = NSCalendar.currentCalendar().components([.Month, .Day, .Hour, .Minute, .Second], fromDate: myString1, toDate: myString2, options: [])
let diff = components.second
print("Difference is \(diff)")

NSDate which is returned is incorrect

I am build a function to get the date for the Chinese new year from the date which is passed from a datePicker. the convertDateFormater converts a string formatted date to a date object. the date which i get back is
Returned date = "03-Feb-2030" for the year "1970-05-22"
but if i run the current date with "NSDate() as Date" i get the right output. for the year 2016.
func convertDateFormater(date: String) -> Date
{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"//this your string date format
dateFormatter.timeZone = NSTimeZone(name: "UTC") as TimeZone!
let date = dateFormatter.date(from: date)
return date!
}
var inputDate1 = convertDateFormater(date: "1970-05-22")
print(inputDate1)
let chineseCalendar = NSCalendar(calendarIdentifier: NSCalendar.Identifier.chinese)!
let formatter: DateFormatter = {
let fmt = DateFormatter()
fmt.dateStyle = .full
fmt.timeStyle = .full
fmt.dateFormat = "dd-MMM-yyyy"
return fmt
}()
var comps = chineseCalendar.components([.year], from: inputDate)
guard let newYear = chineseCalendar.date(from: comps) else { fatalError("no date for \(comps.year)")}
let getNewYear = formatter.string(from: newYear)
print("\(NSDate() as Date) : \(getNewYear) - \(newYear)")
In the Gregorian calendar, there are two eras: the current "Common Era" (abbreviated "CE" and also known as "Anno Domini" or "AD") and "Before Common Era" (abbreviated "BCE" and also known as "Before Christ" or "BC"). So a year number on the Gregorian calendar is ambiguous: "1970" by itself can mean either "1970 CE" or "1970 BCE". We usually assume CE when no era is specified.
I know almost nothing about the Chinese calendar, but I know it has many more eras than the Gregorian calendar, so a year number on the Chinese calendar is even more ambiguous. The code you posted doesn't do anything about eras. So I copied and pasted your code into a playground and made one change:
var comps = chineseCalendar.components([.era, .year], from: inputDate)
// ^^^^^^
The output:
1970-05-22 00:00:00 +0000
2016-11-30 01:40:12 +0000 : 06-Feb-1970 - 1970-02-06 06:00:00 +0000
Indeed, 1970-02-06 was the date of the Chinese new year in 1970 CE on the Gregorian calendar.