If I create a Date() to get the current date and time, I want to create a new date from that but with different hour, minute, and zero seconds, what's the easiest way to do it using Swift? I've been finding so many examples with 'getting' but not 'setting'.
Be aware that for locales that uses Daylight Saving Times, on clock change days, some hours may not exist or they may occur twice. Both solutions below return a Date? and use force-unwrapping. You should handle possible nil in your app.
Swift 3+ and iOS 8 / OS X 10.9 or later
let date = Calendar.current.date(bySettingHour: 9, minute: 30, second: 0, of: Date())!
Swift 2
Use NSDateComponents / DateComponents:
let gregorian = NSCalendar(calendarIdentifier: NSCalendarIdentifierGregorian)!
let now = NSDate()
let components = gregorian.components([.Year, .Month, .Day, .Hour, .Minute, .Second], fromDate: now)
// Change the time to 9:30:00 in your locale
components.hour = 9
components.minute = 30
components.second = 0
let date = gregorian.dateFromComponents(components)!
Note that if you call print(date), the printed time is in UTC. It's the same moment in time, just expressed in a different timezone from yours. Use a NSDateFormatter to convert it to your local time.
swift 3 date extension with timezone
extension Date {
public func setTime(hour: Int, min: Int, sec: Int, timeZoneAbbrev: String = "UTC") -> Date? {
let x: Set<Calendar.Component> = [.year, .month, .day, .hour, .minute, .second]
let cal = Calendar.current
var components = cal.dateComponents(x, from: self)
components.timeZone = TimeZone(abbreviation: timeZoneAbbrev)
components.hour = hour
components.minute = min
components.second = sec
return cal.date(from: components)
}
}
//Increase the day & hours in Swift
let dateformat = DateFormatter()
let timeformat = DateFormatter()
dateformat.dateStyle = .medium
timeformat.timeStyle = .medium
//Increase Day
let currentdate = Date()
let currentdateshow = dateformat.string(from: currentdate)
textfield2.text = currentdateshow
let myCurrentdate = dateformat.date(from: dateTimeString)!
let tomorrow = Calendar.current.date(byAdding: .day, value: 1, to: myCurrentdate) // Increase 1 Day
let tomorrowday = dateformat.string(from: tomorrow!)
text3.text = tomorrowday
text3.isEnabled = false
//increase Time
let time = Date()
let currenttime = timeformat.string(from: time)
text4.text = currenttime
let mycurrenttime = timeformat.date(from: currenttime)!
let increasetime = Calendar.current.date(byAdding: .hour, value: 2, to: mycurrenttime) //increase 2 hrs.
let increasemytime = timeformat.string(from: increasetime!)
text5.text = increasemytime
Related
I'm working to create a function that takes an input duration and an "end" time, and calculates a "start" time based on that criteria.
Example: if the "end" time is 5:00pm and the "duration" is 30 minutes, then the "start" time returned should be 4:30pm.
I'm getting lost in translating between Int/Date/String, so I may need to re-think my entire approach. So far I'm working with the following, which is just a take on this Stack Overflow post:
var userInputEventEndTime: String
var userInputEventDuration: Int
var userInputEventNeedsToStartTime: String
//Manipulate this function with the input parameters
func makeDate(hr: Int, min: Int, sec: Int) -> Date {
var calendar = Calendar(identifier: .gregorian)
let components = DateComponents(hour: hr, minute: min, second: sec)
let hour = calendar.component(.hour, from: calendar.date(from: components)!)
let minutes = calendar.component(.minute, from: calendar.date(from: components)!)
let seconds = calendar.component(.second, from: calendar.date(from: components)!)
return calendar.date(from: components)!
}
Should I be converting the input strings to DateComponents and then doing the math? If so, I'm not sure how to account for minutes converting to hours. Or just go a different direction altogether? Thanks!
The following uses DateComponents and Calendar to calculate the start time
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "hh:mm a"
let calendar = Calendar.current
let dateComponents = DateComponents(calendar: calendar, minute: -userInputEventDuration)
if let endTime = dateFormatter.date(from: userInputEventEndTime),
let startTime = calendar.date(byAdding: dateComponents, to: endTime, wrappingComponents: false) {
userInputEventNeedsToStartTime = dateFormatter.string(from: startTime)
}
Here is the same solution written as a function with an example
func calculateStartTime(from endTime: String, duration: Int) -> String? {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "hh:mm a"
let calendar = Calendar.current
let dateComponents = DateComponents(calendar: calendar, minute: -duration)
if let time = dateFormatter.date(from: endTime),
let startTime = calendar.date(byAdding: dateComponents, to: time, wrappingComponents: false) {
return dateFormatter.string(from: startTime)
}
return nil
}
if let startTime = calculateStartTime(from: "6:00 PM", duration: 30) {
print("Event starts at \(startTime)")
}
Output
Event starts at 05:30 PM
To subtract components from the date, just add their negative values.
I'm trying to get the difference in two Date objects.
I know how to do it basically, which is like this:
let date = Date()
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale.current
print(count)
// print(history[count - 1].value(forKey: "multipleURLs") as! [String])
let latestDate = history[count - 1].value(forKey: "date") as! Date
let calendar = Calendar.current
let components = calendar.dateComponents([.year, .month, .day, .hour], from: date)
let nowDate = calendar.startOfDay(for: date)
let lastDate = calendar.startOfDay(for: latestDate)
let diffDateComponent = (calendar as NSCalendar).components([NSCalendar.Unit.year, NSCalendar.Unit.month, NSCalendar.Unit.day], from: lastDate, to: nowDate, options: NSCalendar.Options.init(rawValue: 0))
print("Status Checked" + String(describing: diffDateComponent.day))
But I'm trying to get the result as a day start from 6 a.m. in the morning instead of 0.
So I did something like this:
let nowDate = calendar.startOfDay(for: date.addingTimeInterval(-3600))
let lastDate = calendar.startOfDay(for: latestDate.addingTimeInterval(-3600))
But it doesn't seem to be working, can anyone help me with this?
This will set each date to 6 AM (in the current locale of the Date):
import Foundation
// set up dates
let calendar = Calendar.current
let date = Date()
if let latestDate = calendar.date(byAdding: .day, value: -5, to: date) {
// set each day to 6 AM
if let nowDate = calendar.date(bySettingHour: 6, minute: 0, second: 0, of: date ),
let lastDate = calendar.date(bySettingHour: 6, minute: 0, second: 0, of: latestDate) {
print( date.description(with: .current),
nowDate.description(with: .current),
lastDate.description(with: .current),
separator: "\n")
// calculate difference in days
if let days = calendar.dateComponents([.day], from: lastDate, to: nowDate).day {
print("Days since: \(days)")
}
}
}
// Thursday, June 8, 2017 at 7:59:42 AM Eastern Daylight Time
// Thursday, June 8, 2017 at 6:00:00 AM Eastern Daylight Time
// Saturday, June 3, 2017 at 6:00:00 AM Eastern Daylight Time
// Days since: 5
Thanks guy, I finally figured it out. In case anyone need it, this is how it's done:
let date = Date()
let dateFormatter = DateFormatter()
dateFormatter.locale = Locale.current
let latestDate = history[count - 1].value(forKey: "date") as! Date
let calendar = Calendar.current
let nowDate = calendar.date(byAdding: .hour, value: -6, to: date)
let lastDate = calendar.date(byAdding: .hour, value: -6, to: latestDate)
let finalNowDate = calendar.startOfDay(for: nowDate!)
let finalLastDate = calendar.startOfDay(for: lastDate!)
let diffDateComponent = calendar.dateComponents([.day], from: finalLastDate, to: finalNowDate)
print("dif\(diffDateComponent.day)")
I need to get a Date object set for tomorrow at a certain time. I can figure out how to change the date to tomorrow but not how to set the time. Here is my function:
func getTomorrowAt(hour: Int, minutes: Int) -> Date {
let calendar = Calendar.current
var date = calendar.date(byAdding: .day, value: 1, to: Date())
// here I need to set the time to hour:minutes
return date!
}
Pass the hours and mins to this function:
func getTomorrowAt(hour: Int, minutes: Int) -> Date {
let today = Date()
let morrow = Calendar.current.date(byAdding: .day, value: 1, to: today)
return Calendar.current.date(bySettingHour: hour, minute: minutes, second: 0, of: morrow)
}
let greg = Calendar(identifier: .gregorian)
let now = Date()
var components = greg.dateComponents([.year, .month, .day, .hour, .minute, .second], from: now)
components.hour = 10
components.minute = 35
components.second = 0
let date = greg.date(from: components)!
func date() -> String {
return NSDateFormatter.localizedStringFromDate(NSDate(), dateStyle: NSDateFormatterStyle.ShortStyle, timeStyle: NSDateFormatterStyle.MediumStyle)
}
var date = date() // 2016. 5. 13. 오전 4:45:16
above code, date obtain korean current value of date every time that i call date()
I'll hope to have refresh new value from NSDate(), and so insert refresh new value into varibles like below code
var yearMonDay = "2016. 5. 13"
var hourMinSec = "오전 4:45:16"
hmmm Are there methods to divide NSDate() into pieces like below code?
yearMonDay = NSDate().?? // refresh date "year: month: day"
hourMinSec = NSDate().?? // refresh date "am/fm hour:minute:second
Splitting up components like hour can be done using the components of the NSCalendar
let today = NSDate()
let calendar = NSCalendar(identifier: NSCalendarIdentifierGregorian)!
let components = calendar.components([.Year, .Month, .Day, .Hour, .Minute, .Second], fromDate: today)
print("\(components.month) \(components.day) \(components.year)")
print("\(components.hour) \(components.minute) \(components.second)")
With the NSDate formatter you can find the names
let formatter = NSDateFormatter()
let monthName = formatter.monthSymbols[components.month-1]
print(monthName)
You can use the NSDateFormatterStyle:
// get the current date and time
let currentDateTime = NSDate()
// initialize the date formatter and set the style
let formatter = NSDateFormatter()
// October 26, 2015
formatter.timeStyle = NSDateFormatterStyle.NoStyle
formatter.dateStyle = NSDateFormatterStyle.LongStyle
formatter.stringFromDate(currentDateTime)
// 6:00:50 PM
formatter.timeStyle = NSDateFormatterStyle.MediumStyle
formatter.dateStyle = NSDateFormatterStyle.NoStyle
formatter.stringFromDate(currentDateTime)
I was facing the struggle of making a timer app, so I thought that now that I solved it I could help others who face the problem. So basically this app counts down to a specific date from the current time. As stack overflow allows a Q and A format I hope that can help you. See the comments for explanations.
Cleaned up and updated with countdown computed on a timer and leading zero String format.
let futureDate: Date = {
var future = DateComponents(
year: 2020,
month: 1,
day: 1,
hour: 0,
minute: 0,
second: 0
)
return Calendar.current.date(from: future)!
}()
var countdown: DateComponents {
return Calendar.current.dateComponents([.day, .hour, .minute, .second], from: Date(), to: futureDate)
}
#objc func updateTime() {
let countdown = self.countdown //only compute once per call
let days = countdown.day!
let hours = countdown.hour!
let minutes = countdown.minute!
let seconds = countdown.second!
countdownLabel.text = String(format: "%02d:%02d:%02d:%02d", days, hours, minutes, seconds)
}
func runCountdown() {
Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
}
Here is the solution of how I managed to create a countdown timer to a specific NSDate, for SO allows Q and A Style Answers.
// here we set the current date
let date = NSDate()
let calendar = NSCalendar.currentCalendar()
let components = calendar.components(.CalendarUnitHour | .CalendarUnitMinute | .CalendarUnitMonth | .CalendarUnitYear | .CalendarUnitDay, fromDate: date)
let hour = components.hour
let minutes = components.minute
let month = components.month
let year = components.year
let day = components.day
let currentDate = calendar.dateFromComponents(components)
// here we set the due date. When the timer is supposed to finish
let userCalendar = NSCalendar.currentCalendar()
let competitionDate = NSDateComponents()
competitionDate.year = 2015
competitionDate.month = 6
competitionDate.day = 21
competitionDate.hour = 08
competitionDate.minute = 00
let competitionDay = userCalendar.dateFromComponents(competitionDate)!
// Here we compare the two dates
competitionDay.timeIntervalSinceDate(currentDate!)
let dayCalendarUnit: NSCalendarUnit = (.CalendarUnitDay | .CalendarUnitHour | .CalendarUnitMinute)
//here we change the seconds to hours,minutes and days
let CompetitionDayDifference = userCalendar.components(
dayCalendarUnit, fromDate: currentDate!, toDate: competitionDay,
options: nil)
//finally, here we set the variable to our remaining time
var daysLeft = CompetitionDayDifference.day
var hoursLeft = CompetitionDayDifference.hour
var minutesLeft = CompetitionDayDifference.minute
Hope that helps you guys if you're facing the same struggle as I have
Cleaned up/updated for latest Swift version of the accepted answer.
// here we set the current date
let date = NSDate()
let calendar = Calendar.current
let components = calendar.dateComponents([.hour, .minute, .month, .year, .day], from: date as Date)
let currentDate = calendar.date(from: components)
let userCalendar = Calendar.current
// here we set the due date. When the timer is supposed to finish
let competitionDate = NSDateComponents()
competitionDate.year = 2017
competitionDate.month = 4
competitionDate.day = 16
competitionDate.hour = 00
competitionDate.minute = 00
let competitionDay = userCalendar.date(from: competitionDate as DateComponents)!
//here we change the seconds to hours,minutes and days
let CompetitionDayDifference = calendar.dateComponents([.day, .hour, .minute], from: currentDate!, to: competitionDay)
//finally, here we set the variable to our remaining time
let daysLeft = CompetitionDayDifference.day
let hoursLeft = CompetitionDayDifference.hour
let minutesLeft = CompetitionDayDifference.minute
print("day:", daysLeft ?? "N/A", "hour:", hoursLeft ?? "N/A", "minute:", minutesLeft ?? "N/A")
//Set countdown label text
countDownLabel.text = "\(daysLeft ?? 0) Days, \(hoursLeft ?? 0) Hours, \(minutesLeft ?? 0) Minutes"
This worked for me.
The only thing that troubles me is that it doesn't really countdown as the user has to refresh the page for it to recount. You can see it "counting" when the user is scrolling up and down cells on a UITableView as the cells do refresh the view.
Another thing is that I have on NSTimeZone of the currentDate "GMT+2:00" as it works for my time but only because I haven't figured out how to use the device NSTimeZone yet.
let releaseDate = "2015-05-02'T'22:00:00:000Z"
let futureDateFormatter = NSDateFormatter()
futureDateFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
let date: NSDate = futureDateFormatter.dateFromString(releaseDate!)!
let currentDate = NSDate();
let currentFormatter = NSDateFormatter();
currentFormatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSSZ"
currentFormatter.timeZone = NSTimeZone(abbreviation: "GMT+2:00")
let diffDateComponents = NSCalendar.currentCalendar().components([NSCalendarUnit.Month, NSCalendarUnit.Day, NSCalendarUnit.Hour, NSCalendarUnit.Minute], fromDate: currentDate, toDate: date, options: NSCalendarOptions.init(rawValue: 0))
let countdown = "\(diffDateComponents.month) m: \(diffDateComponents.day) d: \(diffDateComponents.hour) h: \(diffDateComponents.minute) min"