Convert date with timezone - ios

I am getting date from server: 2022-12-14 20:59:59 +0000
I have view with promo codes, so according to received date I should show after how many seconds it will be expired.
For example if my current date is 2022-12-14 19:59:59 +0000, I must show 60:00 seconds.
If the users timezone is GMT+4, he must see 60:00 seconds as well.
So I use this code:
let currentTime = Int(Date().timeIntervalSince1970)
let expirationDate = model.expirationDate
expiredText = expirationDate.dateStringWithFormat("dd.MM.yyyy")
timeLeft = Int(expirationDate.timeIntervalSince1970) - currentTime
Result is:
currentTime: 2022-12-14 13:48:16 +0000 // my current time is 16:48:16
expirationDate: 2022-12-14 20:59:59 +0000
timeLeft: "0d. 07:11:43"
So Date() returns wrong date.
I tried to use calendar, but result is the same.
let calendar = Calendar(identifier: .gregorian)
let currentDate = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss:Z"
dateFormatter.timeZone = calendar.timeZone
How can I correctly convert my timezone to timezone of received date or vice versa?
Thanks

I think you are making this more complicated than it is.
We have a server timestamp
let serverDate = "2022-12-14 20:59:59 +0000"
that we convert to a Date using a formatter
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ssZ"
Then we want to calculate the difference between the server data and now
if let expirationDate = dateFormatter.date(from: serverDate) {
let components = Calendar.current.dateComponents([.day, .hour, .minute, .second], from: .now, to: expirationDate)
}
and then we can use a DateComponentsFormatter to get the difference as a string
let compFormatter = DateComponentsFormatter()
print(compFormatter.string(from: components))

Related

Not able to convert UTC time

I'm getting this UTC time in string format from the server.."2019-12-18T10:58:40Z"
Now I want to convert it into local time. For that I referred this link. But it's not working..
What I wanted to achieve was to convert UTC time to local time and set a timer based on that time.
This is what I've tried..
var utcTime = "\(json["expirationDate"]!)"
self.dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
let date = self.dateFormatter.date(from: utcTime)
let utcDate = date?.toGlobalTime()
let localDate = utcDate?.toLocalTime()
But I'm getting nil values for the dates..
You don't have milliseconds in your UTC date string example. Your date format should be
self.dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
you have to change this format from
"yyyy-MM-dd'T'HH:mm:ss.SSS'Z'" to "yyyy-MM-dd'T'HH:mm:ss'Z'"**you have to
let utcTime = "2019-12-18T10:58:40Z"
let dateFormatter = DateFormatter.init()
dateFormatter.timeZone = TimeZone(abbreviation: "UTC")!
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss'Z'"
let date = dateFormatter.date(from: utcTime)
print(date)

Convert from string to Date with current timezone

I am using these lines of code to convert Date and time, to the current time zone:
let calendar = Calendar(identifier: .gregorian)
let currentDate = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss:Z"
dateFormatter.timeZone = calendar.timeZone
dateFormatter.string(from:currentDate)
print(dateFormatter.string(from: currentDate))
The print output gives me:
2019-11-19 17:22:55:+0100
I am going to store the date in Realm, so how can I convert this back to a Date()?
Edit; I tried converting it, but it doesn't work:
let calendar = Calendar(identifier: .gregorian)
let currentDate = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss:Z"
dateFormatter.timeZone = calendar.timeZone
let dateString = dateFormatter.string(from:currentDate)
let finalDate = dateFormatter.date(from: dateString)
print(dateString) -> Gives me output: 2019-11-19 18:09:05:+0100 - This is the correct time!
print(finalDate!) -> Gives me output: 2019-11-19 17:09:05 +0000
So the finalDate should store the current time as a Date(), but it doesn't get the correct time.
DateFormatter has an option to convert string to date as well:
let calendar = Calendar(identifier: .gregorian)
let currentDate = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss:Z"
dateFormatter.timeZone = calendar.timeZone
dateFormatter.date(from: yourStringDate)
DateFormatter converts in both directions. Using the same formatter, to convert it back, use .date(from:)
let date = dateFormatter.date(from: string)
Based on your comments, you may be misunderstanding what a Date is. A Date is nothing more and nothing less than a number of seconds since the reference time. It doesn't know anything about time zones. It doesn't know anything about calendars. It doesn't even know anything about minutes or hours. It is only a number of seconds since the reference time (it is literally a small wrapper around a single Double value).
When you print a Date, it calls .description, and as a programmer convenience that is generated by a default DateFormatter that turns it into a human readable string purely for debugging purposes. That string does not imply that the Date has calendar or a time zone attached to it. It's just a programmer convenience. It should never be used by the program itself.
If you want to deal with time zones, you must use a Calendar to compute various DateComponents, or a DateFormatter (which uses a Calendar) to generate a String.

Converting the string to date giving different format [duplicate]

This question already has answers here:
Getting date from [NSDate date] off by a few hours
(3 answers)
Closed 3 years ago.
Converting from string to date and date to string time format is changing the original data.
Tried with dateComponents as well by giving the hour and minute
var calendar = Calendar.current
let components = calendar.dateComponents([.year, .month, .day, .hour], from: calFrom)
calendar.timeZone = .current
// Specify date components
var dateComponents:DateComponents = calendar.dateComponents([.year, .month, .day, .hour], from: Date())
dateComponents.year = components.year
dateComponents.month = components.month
dateComponents.day = components.day
dateComponents.hour = 08//Cutomised hour
dateComponents.minute = 34//Cutomised Minutes
// Create date from components
let someDateTime = calendar.date(from: dateComponents)
print(someDateTime!)
Actual Output:
2019-04-02 03:04:00 +0000
Expected Output:
2019-04-02 08:34:00 +0000
I tried with below code as well. Converting the date to String and manually appending the hour and minutes to the string and converting back to the date.
let calFrom = Date()
let formatter = DateFormatter()
formatter.dateFormat = "dd/MM/yyyy"
var calFromDate = formatter.string(from: calFrom)
calFromDate = calFromDate + " 09" + ":30"
print(calFromDate)
//Output 02/04/2019 09:30
formatter.dateFormat = "dd/MM/yyyy hh:mm"
formatter.locale = Locale.current// set locale to reliable US_POSIX
let date1 = formatter.date(from: calFromDate)
print(date1!)
Actual Output:
2019-04-02 04:00:00 +0000
Expected Output:
02/04/2019 09:30
How to get the exact time that has given in the output?
Date used to update the hour and minute components has UTC timezone so calendar should also have the same timeZone as below,
calendar.timeZone = TimeZone(abbreviation: "UTC")!

How to change the timeZone in SwiftDate?

I have displayed the list of timezones in my app. If user selects a particular timezones, I need to change the local timezone to the selected timezone by the user.
let region = Region(tz: timeZoneName.timeZone , cal: cal, loc: cal.locale!)
let date = Date().inRegion(region: region).absoluteDate
Here is the problem, the region is changed to the selected timezone but the date issuing the local timezone.
A Date contains no timezone. From apple's docs: A specific point in time, independent of any calendar or time zone.
The timezone comes into play as soon as you want to present a date to the user. And that's what a DateFormatter is for. As #AlexWoe89 already pointed out, it let's you convert a string, containing a date into a Date object, but also lets you convert a given date into a string representing the date in the time zone you set to the timeZone property of DateFormatter.
let date = Date()
var dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX")
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm"
dateFormatter.timeZone = TimeZone(identifier: "America/Los_Angeles")
let dateString1 = dateFormatter.string(from: date)
dateFormatter.timeZone = TimeZone(identifier: "Germany/Berlin")
let dateString2 = dateFormatter.string(from: date)
This will store 2017-10-23 04:27 in dateString1, while the same date leads to 2017-10-23 13:27 in dateString2.
You can use DateFormatter as a solution, try something like this:
let dateString = "<yourDateAsString>"
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale(identifier: "en_US_POSIX") // => there are a lot of identifiers you can use
dateFormatter.timeZone = TimeZone(secondsFromGMT: 0)
dateFormatter.defaultDate = Date()
dateFormatter.dateFormat = "dd-MM-yyyy hh:mm” // => your needed time format
let convertedDate = dateFormatter.date(from: dateString)

getting wrong time while set date and time in one nsdate separately in ios

when i'm going set event from app to device calendar. i got wrong time.
i have three date picker one for date and other two for start time and end time for event. i set start date as end date in EKEvent because i have to set event on that day only.
get date from date-picker and store it as startdate and end date as nsdate type. below is my date-picker method
func pickerDate()
{
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "YYYY-MM-dd"
routineStartDate = dateFormatter.string(from: self.startDatePicker.date)
// it is for database entry in string and i get right string
print(routineStartDate)
startDate = self.startDatePicker.date as NSDate
print(startDate)
endDate = startDate
}
below method is for start time where i get time and convert to Time Interval and set it to start date.
func starttime() {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
let then: Date? = self.startTimePicker.date
let difference: TimeInterval? = then?.timeIntervalSinceNow
startDate.addingTimeInterval(difference!)
routineStartTime = dateFormatter.string(from: self.startTimePicker.date)
// it is for database entry in string and i get right string
print(routineStartTime)
}
below method is for end time where i get time from picker and convert to Time Interval and set Time Interval to enddate
func endtime() {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm"
routineEndTime = dateFormatter.string(from: self.endTimePicker.date)
print(routineEndTime)
// it is for database entry in string and i get right string
let then: Date? = self.endTimePicker.date
let difference: TimeInterval? = then?.timeIntervalSinceNow
endDate.addingTimeInterval(difference!)
}
below image showing which date i set in picker
below is My EKEvent method where i create event.
existevent.title = tempDescription
existevent.startDate = startDate as Date
existevent.endDate = endDate as Date
existevent.isAllDay = false
existevent.notes = "This is a note"
existevent.calendar = cal
when i check event in calendar i got Problem, i get wrong time in event.i set start time 12:50 pm end time 1:50 pm on date 27 june 2017 in caledar app. date is set perfectly but why time is not set perfectly ? below image for calendar app.
i have doubt in conversion of time interval and set to date. but what i missing dont know.
please suggest me solution and ideas to solve.
Thank you
you need to convert the time to the desired time zone. Because now the date is set correctly in your timezone, but is displayed in +0000 Screenshot. Use calendar for date representation this
And change your code like this in both methods:
startDate.addingTimeInterval(difference!)
to
self.startDate = startDate.addingTimeInterval(difference!)
and
endDate.addingTimeInterval(difference!)
to
self.endDate = endDate.addingTimeInterval(difference!)
in your case Xcode Warning "Result of call to 'addingTimeInterval' is unused"
Try to convert date, before set it to you "existevent", or when you show it
func convertDate(date:Date) -> Date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm" // or other format
var comp = DateComponents()
let calendar = Calendar.current
comp.hour = Calendar.current.component(.hour, from: date)
comp.minute = Calendar.current.component(.minute, from: date)
comp.timeZone = TimeZone(abbreviation: "GMT")!
return calendar.date(from: comp)!
}

Resources