apply DayLightSavingTime to NSDate - ios

I get a NSDate from a UIDatePicker (timePicker) which is converted to the users time zone but it is one hour off because I'm in Summer Time.
So I tried to check if the User is in Summer Time if yes it should add the time to the NSDate/dateInUserTimezone.
How can I achieve this?
func convertTimeZone() ->NSDate {
var date = timePicker.date
print(date)
var formatter = NSDateFormatter()
let timeZone = NSTimeZone(abbreviation: userTimeZone())
formatter.timeZone = timeZone
formatter.dateFormat = "HH:mm:ss"
var isDaylightSavingTime: Bool {
return NSTimeZone.localTimeZone().daylightSavingTime
}
print(isDaylightSavingTime)
var daylightSavingTimeOffset: NSTimeInterval {
return NSTimeZone.localTimeZone().daylightSavingTimeOffset
}
let dateInUserTimezone = formatter.dateFromString(formatter.stringFromDate(date))
return dateInUserTimezone!
}
func userTimeZone() -> String {
return NSTimeZone.localTimeZone().abbreviation ?? ""
}

NSDate is inherently in UTC (it has no timezone). Best to save/transfer your dates in UTC. Then, you can convert this UTC time stamp to any time zone of your preference. Instead of detecting whether the user is DST or not, try converting to your preferred time zone. Here's an example of how you would convert any date to local time zone.
var date = ...
var myTimeZone = NSTimeZone.localTimeZone()
var df = NSDateFormatter()
df.timeZone = myTimeZone
df.dateFormat = "yyyy.MM.dd G 'at' HH:mm:ss zzz"
df.stringFromDate(date)

Related

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

Calculating date and time based on user's timezone [duplicate]

This question already has answers here:
iOS: Convert UTC NSDate to local Timezone
(15 answers)
Closed 6 years ago.
I have a requirement in which I have a local DB full of dates from a particular timezone and I want to convert this date from that particular timezone to user's local timezone. The way I've implemented is that first I am always converting the DB date to UTC by adding the hours difference and then converting it to user local time zone by taking the time interval using
NSTimeInterval(NSTimeZone.localTimeZone().secondsFromGMT
and adding it to the UTC date. I would like to know that is the approach fine because it worked till now on my limited testing. Also will it account for countries which has Day light saving currently active.
The complete code :
func calculateDate(model:EventModel) -> NSDate
{
let date = model.Date
let startTime = model.StartTime
let arrayForTime = startTime?.componentsSeparatedByString(":")
let arrayForDates = date?.componentsSeparatedByString("-")
let calender = NSCalendar(identifier:NSCalendarIdentifierGregorian)
let year = Int(arrayForDates![2])
let month = Int(arrayForDates![1])
let day = Int(arrayForDates![0])
let hour = Int(arrayForTime![0])! + 3 //UTC - 3 the local time
let minutes = Int(arrayForTime![1])
let dateComponents = NSDateComponents()
dateComponents.day = day!
dateComponents.month = month!
dateComponents.year = year!
dateComponents.hour = hour
dateComponents.minute = minutes!
dateComponents.second = 0
dateComponents.timeZone = NSTimeZone(name: "UTC")
let UTCDate = calender?.dateFromComponents(dateComponents)
let dateLocal = self.getLocalDate(UTCDate!)
return dateLocal
}
func getLocalDate(utcDate:NSDate) -> NSDate
{
let timeInterval = NSTimeInterval(NSTimeZone.localTimeZone().secondsFromGMT)
let localdate = utcDate.dateByAddingTimeInterval(timeInterval)
return localdate
}
Previously I was using this but it was not returning the correct local date for Day light saving countries.
func getLocalDate(utcDate:NSDate) -> NSDate
{
let timeInterval = NSTimeInterval(NSTimeZone.localTimeZone().secondsFromGMT)
// let timeZoneObj = NSTimeZone.localTimeZone()
let localdate = utcDate.dateByAddingTimeInterval(timeInterval)
// let isDayLightSavingOn = timeZoneObj.isDaylightSavingTimeForDate(localdate)
// if(isDayLightSavingOn == true)
// {
// let dayLightTimeInterval = timeZoneObj.daylightSavingTimeOffsetForDate(localdate)
// timeInterval -= dayLightTimeInterval
// }
// localdate = utcDate.dateByAddingTimeInterval(timeInterval)
return localdate
}
Thanks in advance. Cheers !
You don't "convert" the NSDate to a timezone. You simply create a string representation of the NSDate in the user's time zone using a NSDateFormatter. The timeZone of the NSDateFormatter defaults to the user's own timezone, so no adjustments are necessary when displaying it in the user's local timezone. For example:
let date = ... // let's imagine it was "2016-05-18 00:03:34 +0000"
let formatter = NSDateFormatter()
formatter.dateStyle = .LongStyle
formatter.timeStyle = .LongStyle
let userDateString = formatter.stringFromDate(date)
If the user was in GMT/UTC-7 timezone, for example, that would result in:
"May 17, 2016 at 5:03:34 PM PDT"
Clearly, change the dateStyle and timeStyle to format it however best for your user interface. But don't do any adjustments of NSDate objects at all, but rather just build a string representation in the user's own timezone.

How to convert a string to a date, without losing the formatting

I have this date 2015-11-06T18:00:00-0500
My format is yyyy-MM-dd'T'HH:mm:ssZ
i try
let startDateString = "2015-11-06T18:00:00-0500"
let format = NSDateFormatter()
format.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
let startDateBtnEnd = format.dateFromString(startDateString)
println("startDateBtnEnd 2 \(startDateBtnEnd)")
But the log is
startDateBtnEnd 2 Optional(2015-11-07 00:00:00 +0000)
NSDate stores dates in UTC. You can convert it to the same moment in time in any timezone. But after losing too many neurons to mentally convert NSDate from one timezone to another, I decided to add my own extension to NSDate to print it out in the local timezone instead:
extension NSDate {
func toString(timeZone: NSTimeZone = NSTimeZone.localTimeZone()) -> String {
let formatter = NSDateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ssZ"
formatter.timeZone = timeZone
return formatter.stringFromDate(self)
}
}
// Usage:
print("startDateBtnEnd 2 \(startDateBtnEnd.toString())")

Date string to NSDate swift

i'm having an array fill with date string, which i would like to go through and check whether the date is today or yesterday. The date string could look like following:
2015-04-10 22:07:00
So far i've tried just to convert it using dateFormatter, but it keeps returning nil
var dateString = arrayNews[0][0].date as NSString
var dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd hh:mm:ss"
var date = dateFormatter.dateFromString(dateString as String)
println(date)
the sudo code i would like to look something like this
if dateString == currentDate
date = "Today, hh:mm"
else if dateString == currentDate(-1)
date = "Yesterday, hh:mm
else
date = dd. MM, hh:mm
in the else statement the date could be 1. April, 12:00
How can i achieve such a logic?
Without the logic
func getDate(dateStr:String, format:String = "yyyy-MM-dd HH:mm:ss") -> NSString {
var dateFmt = NSDateFormatter()
dateFmt.timeZone = NSTimeZone.defaultTimeZone()
dateFmt.dateFormat = format
let newsDate = dateFmt.dateFromString(dateStr)!
let date = NSDate();
let dateFormatter = NSDateFormatter()
dateFormatter.timeZone = NSTimeZone()
let localDate = dateFormatter.stringFromDate(date)
return ""
}
You have to use yyyy-MM-dd HH:mm:ss instead of yyyy-MM-dd hh:mm:ss
HH: 24h format
hh: 12h format (with AM/PM)
Pay attention with dateFormatter, by default, it use localtime zone.
println() shows the value for GMT time, which is hold by NSDate.
It means, without specifying timezone, when you convert your string 2015-04-10 22:07:00 to NSDatetime, it return a data which is the time at your local time zone is 2015-04-10 22:07:00. As NSDate holds date time in GMT, you will see a different value when you show the value of that NSDate with println().
If your timezone is GMT+2 (2h earlier than GMT), when it's 22h:07 in your place, the GMT time is 20h:07. When you call println() on that NSDate, you see 2015-04-10 20:07:00
To compare 2 NSDate:
let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)
let compareResult = calendar?.compareDate(date, toDate: date2, toUnitGranularity: NSCalendarUnit.CalendarUnitDay)
if (compareResult == NSComparisonResult.OrderedSame) {
println("yes")
} else {
println("no")
}
//to get yesterday, using NSCalendar:
let yesterday = calendar?.dateByAddingUnit(NSCalendarUnit.CalendarUnitDay, value: -1, toDate: date, options: NSCalendarOptions.MatchStrictly)

Why can I not format my NSDate with the specified time zone with NSDateFormatter?

I want to get a date that is represented in a String with a time zone GMT+1 and display it on screen with the local time zone GMT+10.
I have 2 methods, one is for create a date from a String (with GMT+1 timeZone), the other one is to format the date into a String (with localTimeZone GMT+10):
func dateFromString(dateString: String) -> NSDate? {
let dateFormatter = NSDateFormatter()
dateFormatter.timeZone = NSTimeZone(abbreviation: "GMT+1")
dateFormatter.dateFormat = "M/d/yyyy hh:mma"
return dateFormatter.dateFromString(dateString)
}
func stringFromDate(date: NSDate) -> String {
let dateFormatter = NSDateFormatter()
dateFormatter.timeZone = NSTimeZone.localTimeZone()
dateFormatter.timeStyle = NSDateFormatterStyle.ShortStyle
return dateFormatter.stringFromDate(date)
}
In the playground, when I do this:
let date = dateFromString("4/8/2015 1:29am")!
println(date)
println(stringFromDate(date))
I get the following output on the right side:
"Apr 8, 2015, 1:29 AM"
"2015-04-07 15:29:00 +0000"
"1:29 AM"
I don't understand why I don't get what I am expecting and looking for:
"Apr 8, 2015, 1:29 AM"
"2015-04-08 10:29:00 +0000"
"10:29 AM"
What's wrong?
Input formatters need the time zone in their string. Like so:
func dateFromString(dateString: String) -> NSDate? {
let dateFormatter = NSDateFormatter()
dateFormatter.dateFormat = "M/d/yyyy hh:mma z"
return dateFormatter.dateFromString(dateString)
}
let date = dateFromString("4/8/2015 1:29am GMT+01")!
Also note that NSTimeZone names have a two digit offset. Compare in the playground
var oops = NSTimeZone(abbreviation: "GMT+1")
var righteous = NSTimeZone(abbreviation: "GMT+01")
The first is nil, the second is not.
I wouldn't trust the formatting of a time stamp that the debugger prints. In my experience dates are always in UTC regardless of the time zone you set according to the log. Try adding the date as a string to a label on the project and see if it's right.
The reasoning behind this as far as I know is that when you print to the log, all it's doing is calling -description. In the case of NSDate this will return in UTC by definition.

Resources