How to add minutes to custom time in swift2 - ios

What I do is:
How to add minutes to current time in swift
how to add 30 minutes to current time
Here is my code:
endFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
let endTimeString = "2017-01-16 12:58:56"
let endTime = endFormatter.dateFromString(endTimeString)
endTime?.dateByAddingTimeInterval(180) // 3 Minute
print(endTime)
1st answer #rob i tried that one but failed . second answer suggest dateByAddingTimeInterval i am not suer is it is work or not .

You need to use dateByAddingUnit as #Rob doing instead of dateByAddingTimeInterval. The reason you are not getting correct time is may because of TimeZone so try to set timeZone with your NSDateFormatter instance.
endFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
endFormatter.timeZone = NSTimeZone(abbreviation: "UTC")
let endTimeString = "2017-01-16 12:58:56"
let endTime = endFormatter.dateFromString(endTimeString)
//Now add the 3 minute in endTime
let calendar = NSCalendar.currentCalendar()
let date = calendar.dateByAddingUnit(.Minute, value: 3, toDate: endTime, options: [])

let dateWithMinuteInterval = Calendar.current.date(byAdding: DateComponents(minute: 23), to: endTime)!

Related

How would you set a date to a specific value in swift? [duplicate]

I have an NSDate object and I want to set it to an arbitrary time (say, midnight) so that I can use the timeIntervalSince1970 function to retrieve data consistently without worrying about the time when the object is created.
I've tried using an NSCalendar and modifying its components by using some Objective-C methods, like this:
let date: NSDate = NSDate()
let cal: NSCalendar = NSCalendar(calendarIdentifier: NSGregorianCalendar)!
let components: NSDateComponents = cal.components(NSCalendarUnit./* a unit of time */CalendarUnit, fromDate: date)
let newDate: NSDate = cal.dateFromComponents(components)
The problem with the above method is that you can only set one unit of time (/* a unit of time */), so you could only have one of the following be accurate:
Day
Month
Year
Hours
Minutes
Seconds
Is there a way to set hours, minutes, and seconds at the same time and retain the date (day/month/year)?
Your statement
The problem with the above method is that you can only set one unit of
time ...
is not correct. NSCalendarUnit conforms to the RawOptionSetType protocol which
inherits from BitwiseOperationsType. This means that the options can be bitwise
combined with & and |.
In Swift 2 (Xcode 7) this was changed again to be
an OptionSetType which offers a set-like interface, see
for example Error combining NSCalendarUnit with OR (pipe) in Swift 2.0.
Therefore the following compiles and works in iOS 7 and iOS 8:
let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
// Swift 1.2:
let components = cal.components(.CalendarUnitDay | .CalendarUnitMonth | .CalendarUnitYear, fromDate: date)
// Swift 2:
let components = cal.components([.Day , .Month, .Year ], fromDate: date)
let newDate = cal.dateFromComponents(components)
(Note that I have omitted the type annotations for the variables, the Swift compiler
infers the type automatically from the expression on the right hand side of
the assignments.)
Determining the start of the given day (midnight) can also done
with the rangeOfUnit() method (iOS 7 and iOS 8):
let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
var newDate : NSDate?
// Swift 1.2:
cal.rangeOfUnit(.CalendarUnitDay, startDate: &newDate, interval: nil, forDate: date)
// Swift 2:
cal.rangeOfUnit(.Day, startDate: &newDate, interval: nil, forDate: date)
If your deployment target is iOS 8 then it is even simpler:
let date = NSDate()
let cal = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let newDate = cal.startOfDayForDate(date)
Update for Swift 3 (Xcode 8):
let date = Date()
let cal = Calendar(identifier: .gregorian)
let newDate = cal.startOfDay(for: date)
Yes.
You don't need to fiddle with the components of the NSCalendar at all; you can simply call the dateBySettingHour method and use the ofDate parameter with your existing date.
let date: NSDate = NSDate()
let cal: NSCalendar = NSCalendar(calendarIdentifier: NSGregorianCalendar)!
let newDate: NSDate = cal.dateBySettingHour(0, minute: 0, second: 0, ofDate: date, options: NSCalendarOptions())!
For Swift 3:
let date: Date = Date()
let cal: Calendar = Calendar(identifier: .gregorian)
let newDate: Date = cal.date(bySettingHour: 0, minute: 0, second: 0, of: date)!
Then, to get your time since 1970, you can just do
let time: NSTimeInterval = newDate.timeIntervalSince1970
dateBySettingHour was introduced in OS X Mavericks (10.9) and gained iOS support with iOS 8.
Declaration in NSCalendar.h:
/*
This API returns a new NSDate object representing the date calculated by setting hour, minute, and second to a given time.
If no such time exists, the next available time is returned (which could, for example, be in a different day than the nominal target date).
The intent is to return a date on the same day as the original date argument. This may result in a date which is earlier than the given date, of course.
*/
- (NSDate *)dateBySettingHour:(NSInteger)h minute:(NSInteger)m second:(NSInteger)s ofDate:(NSDate *)date options:(NSCalendarOptions)opts NS_AVAILABLE(10_9, 8_0);
Here's an example of how you would do it, without using the dateBySettingHour function (to make sure your code is still compatible with iOS 7 devices):
NSDate* now = [NSDate date];
NSCalendar *gregorian = [[NSCalendar alloc] initWithCalendarIdentifier:NSGregorianCalendar];
NSDateComponents *dateComponents = [gregorian components:(NSYearCalendarUnit | NSMonthCalendarUnit | NSDayCalendarUnit) fromDate:now];
NSDate* midnightLastNight = [gregorian dateFromComponents:dateComponents];
Yuck.
There is a reason why I prefer coding in C#...
Anyone fancy some readable code..?
DateTime midnightLastNight = DateTime.Today;
;-)
Swift 5+
let date = Calendar.current.date(bySettingHour: 0, minute: 0, second: 0, of: Date())
Swift iOS 8 and up: People tend to forget that the Calendar and DateFormatter objects have a TimeZone. If you do not set the desired timzone and the default timezone value is not ok for you, then the resulting hours and minutes could be off.
Note: In a real app you could optimize this code some more.
Note: When not caring about timezones, the results could be OK on one device, and bad on an other device just because of different timezone settings.
Note: Be sure to add an existing timezone identifier! This code does not handle a missing or misspelled timezone name.
func dateTodayZeroHour() -> Date {
var cal = Calendar.current
cal.timeZone = TimeZone(identifier: "Europe/Paris")!
return cal.startOfDay(for: Date())
}
You could even extend the language. If the default timezone is fine for you, do not set it.
extension Date {
var midnight: Date {
var cal = Calendar.current
cal.timeZone = TimeZone(identifier: "Europe/Paris")!
return cal.startOfDay(for: self)
}
var midday: Date {
var cal = Calendar.current
cal.timeZone = TimeZone(identifier: "Europe/Paris")!
return cal.date(byAdding: .hour, value: 12, to: self.midnight)!
}
}
And use it like this:
let formatter = DateFormatter()
formatter.timeZone = TimeZone(identifier: "Europe/Paris")
formatter.dateFormat = "yyyy/MM/dd HH:mm:ss"
let midnight = Date().midnight
let midnightString = formatter.string(from: midnight)
let midday = Date().midday
let middayString = formatter.string(from: midday)
let wheneverMidnight = formatter.date(from: "2018/12/05 08:08:08")!.midnight
let wheneverMidnightString = formatter.string(from: wheneverMidnight)
print("dates: \(midnightString) \(middayString) \(wheneverMidnightString)")
The string conversions and the DateFormatter are needed in our case for some formatting and to move the timezone since the date object in itself does not keep or care about a timezone value.
Watch out! The resulting value could differ because of a timezone offset somewhere in your calculating chain!
Just in case someone is looking for this:
Using SwiftDate you could just do this:
Date().atTime(hour: 0, minute: 0, second: 0)
In my opinion, the solution, which is easiest to verify, but perhaps not the quickest, is to use strings.
func set( hours: Int, minutes: Int, seconds: Int, ofDate date: Date ) -> Date {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
let newDateString = "\(dateFormatter.string(from: date)) \(hours):\(minutes):\(seconds)"
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
return dateFormatter.date(from: newDateString)
}
func resetHourMinuteSecond(date: NSDate, hour: Int, minute: Int, second: Int) -> NSDate{
let nsdate = NSCalendar.currentCalendar().dateBySettingHour(hour, minute: minute, second: second, ofDate: date, options: NSCalendarOptions(rawValue: 0))
return nsdate!
}
Use the current calendar to get the start of the day for the current time.
let today = Calendar.current.startOfDay(for: Date())

How to calculate time (minutes) between two dates in swift?

What do we got: Date+time (format yyyy-mm-dd hh:mm a)
What are we looking for: Time difference in minutes
What operation: NewDate - OldDate
So, I wonder how I could accomplish above goal? I would like to format the date and time to US, regardless from which locale the user has. How can I do that?
Then I will save the 'oldTime' into UserDefaults, and use it for later calculation. The goal is to put the user on delay for 5 minutes and the calculations will be performed to determine if user should be on delay or not.
Just make a function that takes two dates and compares them like this.
import UIKit
func minutesBetweenDates(_ oldDate: Date, _ newDate: Date) -> CGFloat {
//get both times sinces refrenced date and divide by 60 to get minutes
let newDateMinutes = newDate.timeIntervalSinceReferenceDate/60
let oldDateMinutes = oldDate.timeIntervalSinceReferenceDate/60
//then return the difference
return CGFloat(newDateMinutes - oldDateMinutes)
}
//Usage:
let myDateFormatter = DateFormatter()
myDateFormatter.dateFormat = "yyyy-MM-dd HH:mm"
//You'll need both dates to compare, you can get them by just storing a Date object when you first start the timer.
//Then when you need to check it, compare it to Date()
let oldDate: Date = myDateFormatter.date(from: String("2019-06-22 11:25"))
func validateRefresh() {
//do the comparison between the old date and the now date like this.
if minutesBetweenDates(oldDate, Date()) > 5 {
//Do whatever
}
}
You can, of course, change the .dateFormat value on the date formatter to be whatever format you'd like. A great website for finding the right format is: https://nsdateformatter.com/.
You say:
I would like to format the date and time to US, regardless from which locale the user has. How can I do that?
Specify a Locale of en_US_POSIX:
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd hh:mm a"
formatter.locale = Locale(identifier: "en_US_POSIX")
The locale is not the only question.
There’s also a timezone question. For example, you're driving out of Chicago and go from Central to Eastern timezones; do you really want to consider that one hour has passed?
Do you really want to discard seconds? If you do that, the 59 seconds between going from 8:00:00pm to 8:00:59pm will be considered “zero minutes” but the one second between 8:00:59pm and 8:01:00pm will be considered “one minute”.
Frankly, if I wanted to save a locale and timezone invariant date string, I’d suggest using ISO8601DateFormatter.
Then I will save the 'oldTime' into UserDefaults, and use it for later calculation.
If that’s why you’re using this DateFormatter, I’d suggest saving the Date object directly.
UserDefaults.standard.set(oldTime, forKey: "oldTime")
And to retrieve it:
if let oldTime = UserDefaults.standard.object(forKey: "oldTime") as? Date {
...
}
In terms of calculating the number of minutes between two Date objects
let minutes = Calendar.current
.dateComponents([.minute], from: date1, to: date2)
.minute
If you want the number of seconds, you can also use timeIntervalSince:
let seconds = date2.timeIntervalSince(date1)
And if you wanted to show the amount of elapsed time as a nice localized string:
let intervalFormatter = DateComponentsFormatter()
intervalFormatter.allowedUnits = [.minute, .second]
intervalFormatter.unitsStyle = .full
let string = intervalFormatter.string(from: date1, to: date2)
I'm not convinced that your question is the best way to go about accomplishing your aim, but the code below will work.
let dateFormatterNow = DateFormatter()
dateFormatterNow.dateFormat = "yyyy-MM-dd hh:mm a"
dateFormatterNow.timeZone = TimeZone(abbreviation: "EST")
let oldDateString = "2019-06-23 12:44 p"
let oldDate = dateFormatterNow.date(from: oldDateString)
let newDateString = "2019-06-23 12:54 p"
let newDate = dateFormatterNow.date(from: newDateString)
if let oldDate = oldDate, let newDate = newDate {
let diffInMins = Calendar.current.dateComponents([.minute], from: oldDate, to: newDate).minute
print(diffInMins)
}

Get tomorrow's date with Swift 2

I have this code which gives today's date in this formate M/dd/yy
let dateFormater = NSDateFormatter()
dateFormater.dateFormat = "M/dd/yy"
let todayDate = dateFormater.stringFromDate(NSDate())
How can I get the same thing but with next day's date please?
First, you get a NSDate for the day you need, in this example (one day from now is tomorrow):
var oneDayfromNow: Date? {
Calendar.current.date(byAdding: .day, value: 1, to: Date())
}
print(oneDayfromNow)
Then you convert it to your format as string (your case M/dd/yy):
if let oneDayfromNow {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "M/dd/yy"
let str = dateFormatter.string(from: oneDayfromNow)
print(str)
}
It's a bit complicated, but it's all things that you need to know anyway.
Why it's difficult: You would think that you could just take NSDate (timeIntervalSinceNow:24 * 60 * 60), adding one day to now. But when you turn on daylight savings time, then 11:30pm plus 24 hours is 00:30am two days later. When daylight savings time is turned off, then 00:30am plus 24 hours can be 11:30pm on the same day.
So you need to create an NSCalendar object, convert NSDate () into components, add one day to the components, convert back to an NSDate (all that gives you the same time on the next day, handling all special cases), and then format the result as you did now.
I finally used this code to fix it :
let dateFormater = NSDateFormatter()
dateFormater.dateFormat = "M/dd/yy"
let todayDate = dateFormater.stringFromDate(NSDate().dateByAddingTimeInterval(24 * 60 * 60))

how to work with UIDatePicker in Swift?

I built a UI that has 3 UIDatePicker
The first UIDatePicker named date will be for Date only (Mode .Date)
Other UIDatePickers names time_from and time_to will be for Time (From time, To time) (Mode .Time)
Then I add a Button,
When I click the button I need to get two variables:
From_DateTime and To_DateTime
(I need the Date from date UI and the time from time_from, time_to
I try a lot but without the desired result:
let date = date.calendar
let date_components = date.components(.Calendar, fromDate: date.date)
let date_from_components = dateFrom.calendar.components(.Calendar, fromDate: dateFrom.date)
let date_to_components = dateTo.calendar.components(.Calendar, fromDate: dateTo.date)
let n = date.calendar.dateBySettingHour(date_from_components.hour, minute: date_from_components.minute, second: 5, ofDate: dateFrom.date, options: NSCalendarOptions.MatchStrictly)
This is an example of fails trying.
I need a simple way to get From_DateTime and To_DateTime
Thanks
Finally I found a way:
let dateFormatter = NSDateFormatter()
dateFormatter.locale = NSLocale(localeIdentifier: "US")
dateFormatter.dateFormat = "yyyy-MM-dd"
let timeFormatter = NSDateFormatter()
timeFormatter.locale = NSLocale(localeIdentifier: "US")
timeFormatter.dateFormat = " HH:mm"
let date_from = dateFormatter.stringFromDate(date.date) + timeFormatter.stringFromDate(dateFrom.date)
let date_to = dateFormatter.stringFromDate(date.date) + timeFormatter.stringFromDate(dateTo.date)
I am sure there must be another simple way.

Swift Get previous years datetime at GMT+08:00 timezone

I need to get previous 5 years of GMT +08:00 timezone but I'm having trouble of getting the correct timezone.
let today = NSDate()
let gregorian = NSCalendar(calendarIdentifier: NSGregorianCalendar)
gregorian?.timeZone = NSTimeZone(forSecondsFromGMT: 60*60*8)
let offsetComponents = NSDateComponents()
offsetComponents.year = years
let nYearsDate: NSDate = gregorian!.dateByAddingComponents(offsetComponents, toDate: today, options: NSCalendarOptions(0))!
println("getNYearsDate: \(nYearsDate)")
I am getting 2010-07-23 11:44:47 +0000
instead of 2010-07-23 00:00:00 +0800
I need to get
2010-07-23 00:00:00 +0800 and 2010-07-23 23:59:59 +0800
is there anyway to achieve this in Swift and iOS 7.1 above?
You need to reset the time as well. Date periods are also best modeled with NSDateComponents.
// a little trick to get all calendar unit masks
let kAllCalendarUnits = NSCalendarUnit(rawValue: UInt.max)
// normalize the date
let components = NSCalendar.currentCalendar().components(
kAllCalendarUnits, fromDate: NSDate())
components.hour = 0
components.minute = 0
components.second = 0
let dateAtStartOfDay = NSCalendar.currentCalendar().dateFromComponents(components)!
// subtract 5 years
var period = NSDateComponents()
period.year = -5
let finalDate = NSCalendar.currentCalendar().dateByAddingComponents(period,
toDate: dateAtStartOfDay, options: [])!
Note that the method with date components will give you the correct day, regardless if the period contains one or two leap years.
The rest is just a question of how to display this date. This is done with NSDateFormatter. Eg.:
let formatter = NSDateFormatter()
formatter.timeZone = NSTimeZone(forSecondsFromGMT: 60 * 60 * 8)
formatter.dateFormat = "yyyy-MM-dd hh:mm:ss Z"
formatter.stringFromDate(finalDate)
// "2010-07-23 6:00:00 +0800"
In case you are wondering why it says "6:00" instead of "8:00": I ran this code with my machine set to GMT+1, plus summer time +1. Obviously, to get "0:00" you have to subtract the desired time difference again, but that would be 8 hours earlier in the GMT time zone.

Resources