How can I print a new array element every day? - ios

I'm trying to pick a new element of my array every day starting at midnight, and then once all elements have been used, jump back to the start of the array. What would be the best way to do so? Here's what I have so far.
import UIKit
var wordsArray = [String] ()
wordsArray = ["Hallo","Apfel","Geburtstag","Pherd","Angst"]
let date = NSDate ()
let calendar:NSCalendar! = NSCalendar(calendarIdentifier: NSCalendar.Identifier.gregorian)
var dateComponents = DateComponents()
dateComponents.day = 1
while wordsArray (0..<2) {
gregorian.date(byAdding: NSCalendar.Unit.day, value: $0, to: now, options: NSCalendar.Options(rawValue: 0))
}

If I understand you right, you want to use a certain array element every day, and these elements should be chosen cyclically.
So the main problem is how to do something every day at midnight.
This can be achieved using a Timer:
// First determine coming midnight
let calendar = NSCalendar.current
let nextDay = calendar.date(byAdding: .day, value: 1, to: Date())
let comingMidnight = calendar.startOfDay(for: nextDay!)
// Then start a time coming midnight, and repeat it every day
// Please note that 24 * 60 * 60 is not completely correct considering daylight saving times
// Sometimes days have 23 hours and sometimes 25 hours!
_ = Timer.init(fireAt: comingMidnight, interval: 24 * 60 * 60, target: self, selector: Selector(("timerFired")), userInfo: nil, repeats: true)
// And this is the timer callback:
func timerFired(timer: Timer) {
// Here you can select the next element in your array, any do what is required
// For selecting the elements cyclically, see the other answers!
}
This code has not been tested, but it should give you an idea how to proceed.

To wrap around the array use the modulo operator, it devides index / number of items in the array and returns the remainder of the division – in this case always 0...4
let wordsArray = ["Hallo","Apfel","Geburtstag","Pferd","Angst"]
for i in 0..<10 {
print(wordsArray[i % wordsArray.count])
}
Create an index variable in your code
var index = 0
and increment it this way
index = (index + 1) % wordsArray.count

This is the easiest way I could think of.
var wordsArray = [String] ()
wordsArray = ["Hallo","Apfel","Geburtstag","Pherd","Angst"]
let secondsInDay = (60 * 60 * 24)
let dayNumber = Int(NSDate().timeIntervalSince1970 / Double(secondsInDay))
let selectedNumber = dayNumber % wordsArray.count
let chosenWord = wordsArray[selectedNumber]
print(chosenWord)
EDIT: another method hopefully satisfying a complaint
var wordsArray = [String] ()
wordsArray = ["Hallo","Apfel","Geburtstag","Pherd","Angst"]
let calendar = Calendar(identifier: .gregorian)
let date = Date()
let yearNumber = calendar.component(.year, from: date)
let monthNumber = calendar.component(.month, from: date)
let dayNumber = calendar.component(.day, from: date)
let daysInYear = Double(yearNumber) * 12.0 * 365.25
let daysInMonth = Double(monthNumber) * 30.42
let totalNumber = daysInYear + daysInMonth + Double(dayNumber)
let selectedNumber = Int(totalNumber) % wordsArray.count
let chosenWord = wordsArray[selectedNumber]
print(chosenWord)

Related

Adding time to date picker date and time results in same date and time. SWIFT

I have a datePickerthat I use to select a starting date and time, and a durationTextLabelto add minutes to that date and time. I set the duration to be minimum 30 if no text is inserted, but the value in
resulting date and time is identical.
Can you see where I'm mistaking?
Thank you very much as usual.
Here's the function:
func setQueryParameters() {
let dateFormatter = DateFormatter()
var convertedDate: String!
dateFormatter.dateFormat = "yyyy/MM/dd/hh/mm"
convertedDate = dateFormatter.string(from: datePicker.date)
let calendar = Calendar.current
let components = (calendar as NSCalendar).components([.year, .month, .day, .weekday, .hour, .minute] , from: datePicker.date)
let year: Int = components.year!
let month: Int = components.month!
let day: Int = components.day!
let weekday: Int = components.weekday!
let hour: Int = components.hour!
let minute: Int = components.minute!
var duration: Double?
duration = Double(durationTextField.text!)
let endDate = datePicker.date.addingTimeInterval(duration!)
let endComponents = (calendar as NSCalendar).components([.hour, .minute], from: endDate)
let endHour: Int = endComponents.hour!
let endMinute: Int = endComponents.minute!
if durationTextField.text != nil {
duration = Double(durationTextField.text!) ?? 30.00
} else { return}
// Opening Time Query parameter
openingTimeQueryStart = Int("\(String(describing: weekday))"+"00"+"00")!
openingTimeQueryEnd = Int("\(String(describing: weekday))"+"\(String(describing: hour))"+"\(String(describing: minute))")!
print("opening query is \(openingTimeQueryEnd)")
// Closing Time Query parameter
closingTimeQueryStart = Int("\(String(describing: weekday))"+"\(String(endHour))"+"\(String(endMinute))")!
closingTimeQueryEnd = Int("\(String(describing: weekday))"+"00"+"00")!
print("closing time query is \(closingTimeQueryStart)")
// Booking Query parameter
let bookingQueryString = "\(String(describing: year))"+"\(String(describing: month))"+"\(String(describing: day))"+"\(String(describing: weekday))"+"\(String(describing: hour))"+"\(String(describing: minute))"+"\(String(endHour))"+"\(String(endMinute))"
bookingQuery = Int(bookingQueryString)!// ?? openingTimeQuery // found nil unwripping optional
}
There are many problems here.
You actually never make any use of dateFormatter other than creating and then never using convertedDate. So delete that unused code.
You have indicated at duration should be in minutes but you treat it as seconds. You need to multiply by 60 to convert it to minutes.
All of your code for calculating things such as openingTimeQueryEnd depend on each value being two digits but your code doesn't give the desired results.
For example, the line:
openingTimeQueryEnd = Int("\(String(describing: weekday))"+"\(String(describing: hour))"+"\(String(describing: minute))")!
should be rewritten as:
openingTimeQueryEnd = Int(String(format: "%02d%02d%02d", weekday, hour, minute))!
or as:
openingTimeQueryEnd = weekday * 10000 + hour * 100 + minute
Make similar changes to the other similar lines.

CMPedometer data more than 7 days

I am trying to collect steps from CMPedometer for 10 days. It works fine for 7 days but returns 0 for last three days.
Here is the code:
var days:[String] = []
var stepsTaken:[Int] = []
let activityManager = CMMotionActivityManager()
let pedoMeter = CMPedometer()
var cnt = 0
override func viewDidLoad() {
super.viewDidLoad()
getDataForLast10Days()
}
func getDataForLast10Days() {
if(CMPedometer.isStepCountingAvailable()){
let serialQueue : DispatchQueue = DispatchQueue(label: "com.example.MyQueue", attributes: .concurrent)
let formatter = DateFormatter()
formatter.dateFormat = "d MMM"
serialQueue.sync(execute: { () -> Void in
let today = NSDate()
for day in 1...10{
let from = NSDate(timeIntervalSinceNow: Double(-7+day) ))
let hour = Calendar.current.component(.hour, from: from as Date)
let min = Calendar.current.component(.minute, from: from as Date)
let sec = Calendar.current.component(.second, from: from as Date)
let timeToSub = (hour * 60 + min) * 60 + sec
let fromDate = NSDate(timeIntervalSinceNow: (Double(-10+day) * (86400 ) ) - Double(timeToSub))
let toDate = NSDate(timeIntervalSinceNow: (Double(-10+day+1) * (86400) ) - Double(timeToSub))
let dtStr = formatter.string(from: (toDate as Date))
self.pedoMeter.queryPedometerData(from: fromDate as Date , to: toDate as Date) { (data : CMPedometerData!, error) -> Void in
//print("From Date: \(fromDate)","\n\n")
if(error == nil){
// print(data,"\n\n")
print("\(dtStr) : \(data.numberOfSteps)")
self.days.append(dtStr)
self.stepsTaken.append(Int(data.numberOfSteps))
}
}
}
})
}
}
But as the days increase since I have created the app, data increases for one day everyday. It's been 2 days since I created the app. It has data for 9 days and so on. How do I tackle this?
Please let me know what is wrong.
Everything is alright.
According to the method definition for the instance method queryPedometerData(from:to:withHandler:)
Only the past seven days worth of data is stored and available for you
to retrieve. Specifying a start date that is more than seven days in
the past returns only the available data.
See Apple's Documentation here.

Extract the time closest to the current time in the time array. University Circular Bus Arrival Notification System

I am going to provide a circulation bus notification system within the university.
I want to extract the time that is closest to the current time in the time array(gateArray) and let me know how many minutes I have left to arrive.
For example, if the array gateArray = ["07:40", "08:00", "08:16", "08:32", "08:48", "09:04", "09:20"],
If the current time is 08:03, the output time from the array is 08:16 instead of 08:00, and the difference between departing time and current time is 08:16 (departing time) - 08:03 (Current time) to calculate the time interval and display UITextView ->> "departing after 13 minutes".
Current time 09:00 am >> GateArray to "09:04" Extraction >> Departure after 4 minutes "
Current time 09:05 am >> GateArray to "09:20" Extraction >> "Departure after 15 minutes"
Swift 3 version with added handling of next day case:
import UIKit
struct ArrivalDataContainer {
var date = Date()
var timeString = "00:00"
var currentMinuteDifference = 0
}
let currentDate = Date()
let unitFlags: Set = Set<Calendar.Component>([.day, .month, .year])
var components = NSCalendar.current.dateComponents(unitFlags, from: currentDate)
let gateArray = ["07:40", "08:00", "08:16", "08:32", "08:48", "09:04", "09:20", "23:00"]
var arrivalArray = [ArrivalDataContainer]()
for timeString in gateArray {
let timeAndMinutes = timeString.components(separatedBy: ":")
components.setValue(Int(timeAndMinutes[0])!, for: .hour)
components.setValue(Int(timeAndMinutes[1])!, for: .minute)
let newDate = NSCalendar.current.date(from: components)
let difference = NSCalendar.current.dateComponents(Set<Calendar.Component>([.minute]), from: currentDate, to: newDate!).minute
let dataContainer = ArrivalDataContainer(date: newDate!, timeString: timeString, currentMinuteDifference: difference!)
arrivalArray.append(dataContainer)
}
let minimumPositiveDifference = arrivalArray.filter{ $0.currentMinuteDifference > 0 }.sorted(by: { $0.currentMinuteDifference < $1.currentMinuteDifference }).first
if let firstWithinSameDay = minimumPositiveDifference {
print("Departure in \(firstWithinSameDay.currentMinuteDifference) minute(s)")
}
else {
let largestNegativeDifference = arrivalArray.sorted(by: { $0.currentMinuteDifference < $1.currentMinuteDifference }).first
print("Next departure \(largestNegativeDifference?.timeString)")
}
Swift 2 version which was the original answer.
import UIKit
struct ArrivalDataContainer {
var date = NSDate()
var timeString = "00:00"
var currentMinuteDifference = 0
}
let currentDate = NSDate()
let unitFlags: NSCalendarUnit = [.Day, .Month, .Year]
let components = NSCalendar.currentCalendar().components(unitFlags, fromDate: currentDate)
let gateArray = ["07:40", "08:00", "08:16", "08:32", "08:48", "09:04", "09:20", "23:00"]
var arrivalArray = [ArrivalDataContainer]()
for timeString in gateArray {
let timeAndMinutes = timeString.componentsSeparatedByString(":")
components.setValue(Int(timeAndMinutes[0])!, forComponent: .Hour)
components.setValue(Int(timeAndMinutes[1])!, forComponent: .Minute)
let newDate = NSCalendar.currentCalendar().dateFromComponents(components)
let difference = NSCalendar.currentCalendar().components([.Minute], fromDate: currentDate, toDate: newDate!, options: []).minute
let dataContainer = ArrivalDataContainer(date: newDate!, timeString: timeString, currentMinuteDifference: difference)
arrivalArray.append(dataContainer)
}
let minimumPositiveDifference = arrivalArray.filter{ $0.currentMinuteDifference > 0 }.sort({ $0.currentMinuteDifference < $1.currentMinuteDifference })[0].currentMinuteDifference
print("Departure in \(minimumPositiveDifference) minute(s)")
Represent the arrival times as Date
Get times from string
Get difference from current time and arrival dates
Select the minimum difference and print departure interval string
Still need to figure out if the first on the next day is the closest one. It might be the one with the most negative minute difference.

Swift countdown timer labels for Days/Hours/Minutes/Seconds

I'm creating a countdown timer that counts down to an NSDate set in a UIDatePicker. I have a label that shows the date we're counting down to and that works fine.
What I'm also trying to add is labels for the number of whole days left and number of hours/minutes/seconds left in the current day (i.e. never more than 23/59/59) Here's what I've done at the minute but it obviously shows the values for the whole countdown. Hoping someone can help me work out the correct logic here.
let secondsLeft = sender.date.timeIntervalSinceDate(NSDate())
hoursLabel.text = String(secondsLeft % 3600)
minutesLabel.text = String((secondsLeft / 60) % 60)
secondsLabel.text = String(secondsLeft % 60)
I guess what I'm looking for is some swift equivalent of the datetime class you get in php
Got it - for Swift 2
let calendar = NSCalendar.currentCalendar()
let components = calendar.components([.Day, .Hour, .Minute, .Second], fromDate: NSDate(), toDate: sender.date, options: [])
daysLabel.text = String(components.day)
hoursLabel.text = String(components.hour)
minutesLabel.text = String(components.minute)
secondsLabel.text = String(components.second)
Take a look at the NSCalendar class. Specifically look at the method
components:fromDate:toDate:options: That lets you take 2 dates and calculate the difference between them using whatever units you specify.
It's also localizable, so if you use the current calendar and the user uses the Chinese, Hebrew, or Arabic calendar then the calculations will give you results correct for that calendar.
Here's a Swift 4 version of Chris Byatt's answer that is also playground-friendly:
import UIKit
let calendar = Calendar.current
let now = Date()
let futureDate = Date.distantFuture
let components = calendar.dateComponents([.day, .hour, .minute, .second], from: now, to: futureDate)
let daysLabel = UILabel()
let hoursLabel = UILabel()
let minutesLabel = UILabel()
let secondsLabel = UILabel()
daysLabel.text = String(describing: components.day)
hoursLabel.text = String(describing: components.hour)
minutesLabel.text = String(describing: components.minute)
secondsLabel.text = String(describing: components.second)
print(components) // day: 723942 hour: 23 minute: 56 second: 0 isLeapMonth: false
// Bonus: here's an easy way to print grammatically correct labels based on numbers
if let seconds = components.second {
let labelText = "\(seconds) \(seconds == 1 ? "second" : "seconds")"
print(labelText) // 0 seconds, 1 second, 2 seconds, etc.
}
Only Copy and Paste this code :
#IBOutlet var countDownLabel: UILabel!
var count = 10800
override func viewDidLoad() {
super.viewDidLoad()
var timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(update), userInfo: nil, repeats: true)
}
func timeString(time: TimeInterval) -> String {
let hours = Int(time) / 3600
let minutes = Int(time) / 60 % 60
let seconds = Int(time) % 60
return String(format:"%02i:%02i:%02i", hours, minutes, seconds)
}
#objc func update() {
let time = timeString(time: TimeInterval(count))
count = count - 1
countDownLabel.text = time
}

How to add minutes to current time in swift

I am new to Swift and am trying a scheduler. I have the start time selected and I need to add 5 minutes (or multiples of it) to the start time and display it in an UILabel?
#IBAction func timePickerClicked(sender: UIDatePicker) {
var dateFormatter = NSDateFormatter()
dateFormatter.timeStyle = NSDateFormatterStyle.ShortStyle
var dateStr = dateFormatter.stringFromDate(startTime.date)
let sttime = dateStr
startTimeDisplay.text = dateStr
}
// How to advance time by 5 minutes for each section based on the start time selected and display time
// section 1 = start time + 5
// section 2 = start time + 10*
Two approaches:
Use Calendar and date(byAdding:to:wrappingComponents:). E.g., in Swift 3 and later:
let calendar = Calendar.current
let date = calendar.date(byAdding: .minute, value: 5, to: startDate)
Just use + operator (see +(_:_:)) to add a TimeInterval (i.e. a certain number of seconds). E.g. to add five minutes, you can:
let date = startDate + 5 * 60
(Note, the order is specific here: The date on the left side of the + and the seconds on the right side.)
You can also use addingTimeInterval, if you’d prefer:
let date = startDate.addingTimeInterval(5 * 60)
Bottom line, +/addingTimeInterval is easiest for simple scenarios, but if you ever want to add larger units (e.g., days, months, etc.), you would likely want to use the calendrical calculations because those adjust for daylight savings, whereas addingTimeInterval doesn’t.
For Swift 2 renditions, see the previous revision of this answer.
You can use Calendar's method
func date(byAdding component: Calendar.Component, value: Int, to date: Date, wrappingComponents: Bool = default) -> Date?
to add any Calendar.Component to any Date. You can create a Date extension to add x minutes to your UIDatePicker's date:
Xcode 8 and Xcode 9 • Swift 3.0 and Swift 4.0
extension Date {
func adding(minutes: Int) -> Date {
return Calendar.current.date(byAdding: .minute, value: minutes, to: self)!
}
}
Then you can just use the extension method to add minutes to the sender (UIDatePicker):
let section1 = sender.date.adding(minutes: 5)
let section2 = sender.date.adding(minutes: 10)
Playground testing:
Date().adding(minutes: 10) // "Jun 14, 2016, 5:31 PM"
Swift 4:
// add 5 minutes to date
let date = startDate.addingTimeInterval(TimeInterval(5.0 * 60.0))
// subtract 5 minutes from date
let date = startDate.addingTimeInterval(TimeInterval(-5.0 * 60.0))
Swift 5.1:
// subtract 5 minutes from date
transportationFromDate.addTimeInterval(TimeInterval(-5.0 * 60.0))
extension Date {
func withAddedMinutes(minutes: Double) -> Date {
addingTimeInterval(minutes * 60)
}
func withAddedHours(hours: Double) -> Date {
withAddedMinutes(minutes: hours * 60)
}
}
useCase
let anHourFromNow = Date().withAddedHours(hours: 1)
let aMinuteFromNow = Date().withAddedMinutes(minutes: 1)
You can use in swift 4 or 5
let date = Date()
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd H:mm:ss"
let current_date_time = dateFormatter.string(from: date)
print("before add time-->",current_date_time)
//adding 5 miniuts
let addminutes = date.addingTimeInterval(5*60)
dateFormatter.dateFormat = "yyyy-MM-dd H:mm:ss"
let after_add_time = dateFormatter.string(from: addminutes)
print("after add time-->",after_add_time)
output:
before add time--> 2020-02-18 10:38:15
after add time--> 2020-02-18 10:43:15
You can do date arithmetic by using NSDateComponents. For example:
import Foundation
let comps = NSDateComponents()
comps.minute = 5
let cal = NSCalendar.currentCalendar()
let r = cal.dateByAddingComponents(comps, toDate: NSDate(), options: nil)
It is what you see when you try it in playground
NSDate.init with timeIntervalSinceNow:
Ex:
let dateAfterMin = NSDate.init(timeIntervalSinceNow: (minutes * 60.0))
Save this little extension:
extension Int {
var seconds: Int {
return self
}
var minutes: Int {
return self.seconds * 60
}
var hours: Int {
return self.minutes * 60
}
var days: Int {
return self.hours * 24
}
var weeks: Int {
return self.days * 7
}
var months: Int {
return self.weeks * 4
}
var years: Int {
return self.months * 12
}
}
Then use it intuitively like:
let threeDaysLater = TimeInterval(3.days)
date.addingTimeInterval(threeDaysLater)
Swift 3:
let minutes: TimeInterval = 1 * 60
let nowPlusOne = Date() + minutes
I think the simplest will be
let minutes = Date(timeIntervalSinceNow:(minutes * 60.0))
In case you want unix timestamp
let now : Date = Date()
let currentCalendar : NSCalendar = Calendar.current as NSCalendar
let nowPlusAddTime : Date = currentCalendar.date(byAdding: .second, value: accessTime, to: now, options: .matchNextTime)!
let unixTime = nowPlusAddTime.timeIntervalSince1970

Resources