Swift: DatePicker-Timer? - swift

Hey!
Here's my problem:
So I have a datepicker which is primarily used to send messages when the set time is reached. However, I would like to see the time run out (timer-like) until the time is reached. Best in the format (hh:mm:ss), because the datepicker is set in the timer format.
I am only a beginner in programming. So I don't know what to do :/
I would be very happy if someone could help me!
Many thanks in advance.
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
let competitionDate = self.datepicker.isSelected
let competition = userCalendar.date(from: competitionDate as DateComponents)!
let CompetitionDifference = calendar.dateComponents([.hour, .minute, .second], from:
currentDate!, to: competition)
let hoursLeft = CompetitionDifference.hour
let minutesLeft = CompetitionDifference.minute
let secondsLeft = CompetitionDifference.second
print("hours:", hoursLeft ?? "N/A", "minutes:", minutesLeft ?? "N/A", "seconds:",
secondsLeft ?? "N/A")
countDownLabel.text = "\(daysLeft ?? 0) hours, \(hoursLeft ?? 0) minutes, \(minutesLeft
?? 0) seconds"

First, you just can't write :
let competition = userCalendar.date(from: competitionDate as DateComponents)!
it will just trigger an error if competitionDate is not a DateComponents but say, a Date!
Then, if you just want string representations of quantities of time DateComponentsFormatter is for you
try :
let date = Date()
let calendar = Calendar.current
let userCalendar = Calendar.current
let competitionDate = date + 4899
let comps = userCalendar.dateComponents([.year, .month, .day, .hour, .minute, .second], from: competitionDate)
let formatter = DateComponentsFormatter()
formatter.unitsStyle = .full
formatter.string(from: date, to: competitionDate) // "1 hour, 21 minutes, 39 seconds"
formatter.unitsStyle = .short
formatter.string(from: date, to: competitionDate) // "1 hr, 21 min, 39"secs"
formatter.unitsStyle = .brief
formatter.string(from: date, to: competitionDate) // "1hr 21min 39secs"
formatter.unitsStyle = .abbreviated
formatter.string(from: date, to: competitionDate) // "1h 21m 39s"
formatter.unitsStyle = .positional
formatter.string(from: date, to: competitionDate) // "1:21:39"
formatter.includesTimeRemainingPhrase = true
formatter.string(from: date, to: competitionDate) // "1:21:39 remaining"

Related

Start and end date of next week swift

I need to get date like "31 of January - 6 of February"
I used next code:
let calendar = Calendar(identifier: .gregorian)
let dateFormatter = DateFormatter()
let weekday = 1
let sundayComponents = DateComponents(calendar: calendar, weekday: weekday)
let nextSunday = calendar.nextDate(after: Date(), matching: sundayComponents, matchingPolicy: .nextTimePreservingSmallerComponents)
I need to take all this period from Monday to Sunday
You can use dateInterval(of:start:interval:for:):
let formatter = DateFormatter()
let calendar: Calendar = .current
let now = Date()
let weekFromNow = calendar.date(byAdding: .weekOfYear, value: 1, to: now)!
var start = weekFromNow
var interval: TimeInterval = 0
guard calendar.dateInterval(of: .weekOfYear, start: &start, interval: &interval, for: weekFromNow) else { return }
let end = calendar.date(byAdding: .day, value: -1, to: start.addingTimeInterval(interval))!
// or let end = start.addingTimeInterval(interval - 1)
// or let end = calendar.date(byAdding: .day, value: 6, to: start)!
print(formatter.string(from: start), "-", formatter.string(from: end))
This will honor the “start of week” on your device.

How do you get all the 4 (or 5) separate weeks in a month from Date() in swift?

I managed to get data query with "nextDate" property of type Date() in a particular month. In other words all data with dates within that particular month will appear on my tableview when queried. Using the code below and with tweaks I also managed to extract data from the previous and next month.
func loadMonthEvents() {
let date = Date()
let calendar = Calendar.current
var beginningOfMonth: Date?
var endOfMonth: Date?
beginningOfMonth = calendar.dateInterval(of: .month, for: date)?.start
endOfMonth = calendar.dateInterval(of: .month, for: date)?.end
monthEvents = realm.objects(Events.self).filter("nextDate BETWEEN %#", [beginningOfMonth, endOfMonth]).sorted(byKeyPath: "nextDate", ascending: true)
}
Now I want to be able to separate those data according to the week of the month. In my tableView the will be 5 separate headers representing week 1, week 2, week 3, week 4 and week 5(if any). Each separate header will show only event for that week. I tried to apply the weekOfMonth in calendar but it just dont work. Thank you in advance.
You could get the range of weeks from your two dates by doing
let w1 = calendar.dateComponents([.weekOfYear], from: beginningOfMonth!)
print(w1.weekOfYear)
let w2 = calendar.dateComponents([.weekOfYear], from: endOfMonth!)
print(w2.weekOfYear)
And then you could do the same for the date of each event to group the event to a specifik week
Here is the snippet to find out first and last day of week . You can do this by adding .weekOfMonth to the date component . Go through this official link and apply accordingly as per your requirement for fetch.
Now i had added two functions / or two button action through which you can get previous week and next week of the month.
var currentDate = Date()
func weekCalculation()
{
let calendar = NSCalendar.current
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
// dateFormatter.dateStyle = .medium
var componentsNow = calendar.dateComponents([.year, .month, .weekOfMonth, .weekday], from: currentDate)
componentsNow.setValue(1, for: .weekday)
firstDayOfWeek = calendar.date(from: componentsNow)!
print(firstDayOfWeek)
componentsNow.setValue(7, for: .weekday)
lastDayOfWeek = calendar.date(from: componentsNow)!
print(lastDayOfWeek)
let addDaysCount = 0
var comps = DateComponents()
comps.setValue(addDaysCount, for: .weekday)
var comps1 = DateComponents()
comps1.setValue(-6, for: .day)
let newDate1 = calendar.date(byAdding: comps1, to: lastDayOfWeek)
let newDate2 = calendar.date(byAdding: comps, to: lastDayOfWeek)
// print(newDate1!,newDate2!)
let firstDay = dateFormatter.string(from: newDate1!)
let lastDay = dateFormatter.string(from: newDate2!)
// ShowBanner(title: "", subtitle: firstDay)
let dF = DateFormatter()
dF.dateFormat = "d MMMM yyyy"
let fDayToShow = dF.string(from: newDate1!)
let lDayToShow = dF.string(from: newDate2!)
let dateString = String(format: "%# - %#",fDayToShow,lDayToShow)
print(firstDay,lastDay)
}
#IBAction func nextWeekBtnPressed(sender: UIButton)
{
let calendar = NSCalendar.current
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
// dateFormatter.dateStyle = .medium
let dF = DateFormatter()
dF.dateFormat = "d MMMM yyyy"
let addDaysCount = 7
var comps = DateComponents()
comps.setValue(addDaysCount, for: .weekday)
var comps1 = DateComponents()
comps1.setValue(3, for: .day)
let newDate1 = calendar.date(byAdding: comps1, to: lastDayOfWeek)
let newDate2 = calendar.date(byAdding: comps, to: lastDayOfWeek)
let firstDay = dateFormatter.string(from: newDate1!)
let lastDay = dateFormatter.string(from: newDate2!)
let fDayToShow = dF.string(from: newDate1!)
let lDayToShow = dF.string(from: newDate2!)
//print(firstDay,lastDay)
let dateString = String(format: "%# - %#",fDayToShow,lDayToShow)
//print(dateString)
weekCalculation()
}
#IBAction func previousWeekBtnPressed(sender: UIButton)
{
let calendar = NSCalendar.current
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd"
// dateFormatter.dateStyle = .medium
let addDaysCount = -7
var comps = DateComponents()
comps.setValue(addDaysCount, for: .weekday)
var comps1 = DateComponents()
comps1.setValue(-10, for: .day)
let newDate1 = calendar.date(byAdding: comps1, to: lastDayOfWeek)
let newDate2 = calendar.date(byAdding: comps, to: lastDayOfWeek)
let firstDay = dateFormatter.string(from: newDate1!)
let lastDay = dateFormatter.string(from: newDate2!)
let dF = DateFormatter()
dF.dateFormat = "d MMMM yyyy"
let fDayToShow = dF.string(from: newDate1!)
let lDayToShow = dF.string(from: newDate2!)
let dateString = String(format: "%# - %#",fDayToShow,lDayToShow)
weekCalculation()
}

String conversion to sec min and hour

i have a time string
duration = "00:01:28"
i want to show like 28 sec ,1 min. how to get separate component as seconds,minute and hour.
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm:ss"
let date = dateFormatter.date(from:duration)
let calendar = Calendar.current
let comp = calendar.dateComponents([.hour, .minute], from: date!)
let hour = comp.hour
let minute = comp.minute
let sec = comp.second
print(sec)
print(minute)
I tried this code but I got a nil in the print statement.
Almost. Of course sec prints nil because you didn't specify the second component.
To print the requested string format I recommend DateComponentsFormatter
let duration = "00:01:28"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "HH:mm:ss"
let date = dateFormatter.date(from:duration)
let components = Calendar.current.dateComponents([.hour, .minute, .second], from: date!)
let componentsFormatter = DateComponentsFormatter()
componentsFormatter.allowedUnits = [.hour, .minute, .second]
componentsFormatter.unitsStyle = .short
componentsFormatter.string(from: components) // "1 min, 28 secs"

How to change the current day's hours and minutes in Swift?

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

How to make a countdown to date Swift

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"