Trying to figure out why the following code results in 90,000 which is exactly 1 hour over a day. The created dates are both set to noon of consecutive days so the answer should be 86,400 (24*60*60).
let currentCalendar = NSCalendar.currentCalendar();
let components1 = NSDateComponents()
components1.year = 2015
components1.month = 11
components1.day = 1
components1.hour = 12
components1.minute = 0
components1.second = 0
let myDate1 = currentCalendar.dateFromComponents(components1)!
let components2 = NSDateComponents()
components2.year = 2015
components2.month = 10
components2.day = 31
components2.hour = 12
components2.minute = 0
components2.second = 0
let myDate2 = currentCalendar.dateFromComponents(components2)!
let difference = myDate1.timeIntervalSinceDate(myDate2)
Running swift 2 (Xcode 7.0)
Daylight savings time ends on Nov 1, 2015. The 25-hour difference is correct. There will also be a 23-hour day in the spring when DST begins.
This is why, if you want to be sure to get the same clock time on another date, you can’t just add or subtract multiples of 24 hours.
This only goes for places that observe DST, which is probably why some commenters on the original question are seeing a 24-hour difference in their local time zone.
Related
Using date format "EEEE:dd:MMM:HH:mm" returns the correct date and time, however, the day of the week is incorrect. For example a 750 nautical mile voyage conducted at 7.5 knots will take 100 hours. If I use my code to calculate the arrival time using a start of, say, Friday 1 Nov at 12:00 it returns Sunday 5 Nov at 16:00. Time and date are correct but day of the week is not. Should be Tuesday.
#IBAction func Calculate(_ sender: UIButton) {
let userCalendar = Calendar.current
let dateMakerFormatter = DateFormatter()
dateMakerFormatter.dateFormat = "EEEE:dd:MMM:HH:mm"
let distance = (Distance.text! as NSString).floatValue
let speed = (GndSpd.text! as NSString).floatValue
let calcDT = ((distance / speed) * 3600)
if var date = dateMakerFormatter.date(from: (DTG.text!)) {
date = dateMakerFormatter.date(from: (DTG.text!))!
var timeAdj = DateComponents()
timeAdj.second = Int(calcDT)
if var adj = userCalendar.date(byAdding: timeAdj, to: date) {
adj = userCalendar.date(byAdding: timeAdj, to: date)!
CalcDTG.text = dateMakerFormatter.string(from: adj)
}
}
}
You should use d for Day, not D
dateMakerFormatter.dateFormat = "EEEE:dd:MMM:HH:mm"
DateFormatter
You can't say the day of the week is incorrect when you're not giving a year.
The date formatter seems to ignore the day of the week when creating a date:
let dateMakerFormatter = DateFormatter()
dateMakerFormatter.dateFormat = "EEEE:dd:MMM:HH:mm"
let date = dateMakerFormatter.date(from: "Friday:01:Nov:12:00")!
print(date) -> 2000-11-01 12:00:00 +0000
print(dateMakerFormatter.string(from: date)) -> Wednesday:01:Nov:12:00
Hey presto, you're now in the year 2000, where 5 November did fall on a Sunday.
The important takeaway you need is that you should never, ever, ever, use strings to pass around date values in your code. Use Date. If you're getting a date from an API response, change it to a date on ingestion. If you're getting one from user entry, use a date picker or other control. If you're getting one from a string the user is typing in, I'd politely suggest you're making unnecessary work for yourself, but do make sure you fill in all the details the user doesn't give you.
I have 2 TimeIntervals, which just represent date-agnostic times of day (e.g. 8:00 AM and 5:00 PM). So 0 represents exactly midnight, in this case, and 29,040 represents 8:04 AM. I want to check if the phone's time of day is between the two TimeIntervals.
I found a few similar Stack Overflow questions, but none of them really dealt with TimeIntervals. It seems like just using start <= Date().timeIntervalSinceReferenceDate <= end or something wouldn't work, because it would return a huge value.
What's the best way to handle this type of situation in Swift 3?
Edit: To clarify, I don't need to worry about things like daylight savings. As an example, assume that the user only wants certain things in the app to happen between the hours of X and Y, where X and Y are given to me as TimeInterval values since midnight. So it should be sufficient to check if the phone's TimeInterval since midnight on a typical day is between X and Y before completing the action.
Date().timeIntervalSinceReferenceDate returns the number of seconds since Jan 1, 2000 so no doubt it's a huge number.
It's inadvisable to store time as seconds since midnight due to this naggy little thing called Daylight Saving Time. Every year, different countries do it on different days and on different hours. For example, even though Britain and France change their clock on the same day (March 26, 2017), one makes the shift from 1AM to 2AM, the other goes from 2AM to 3AM. That's very easy to make for a mess!
Use DateComponents instead:
let calendar = Calendar.current
let startTimeComponent = DateComponents(calendar: calendar, hour: 8)
let endTimeComponent = DateComponents(calendar: calendar, hour: 17, minute: 30)
let now = Date()
let startOfToday = calendar.startOfDay(for: now)
let startTime = calendar.date(byAdding: startTimeComponent, to: startOfToday)!
let endTime = calendar.date(byAdding: endTimeComponent, to: startOfToday)!
if startTime <= now && now <= endTime {
print("between 8 AM and 5:30 PM")
} else {
print("not between 8 AM and 5:30 PM")
}
I ended up using DateComponents to calculate a TimeInterval.
let components = Calendar.current.dateComponents(
[.hour, .minute, .second], from: Date())
guard let seconds = components.second,
let minutes = components.minute,
let hours = components.hour else
{
return false
}
let currentTime = Double(seconds + minutes * 60 + hours * 60 * 60)
return startTime <= currentTime && currentTime <= endTime
I need to find difference between current time (in seconds) and future start time (fetched from my web service in seconds).
I have coded the following :
let currentTime = Int64(Date().timeIntervalSince1970)
var time = Int64(timeArr[indexPath.row])
print("\(currentTime) vs \(time)")
time = time - currentTime
print("difference in time : \(time)")
let seconds = time % 60
let minutes = (time / 60) % 60
let hours = (time / 3600)
My console shows me this output:
1480400929 vs 1480552620
difference in time : 151691
The problem is that my current time is Tue Nov 29 2016 11:58:49 and the start time is 2016-11-30 17:37:00 so the difference in hours should come to around 30 hours whereas it takes the times in different time zones due to which it comes to around 42 hours. How do I fix this? I have gone through many questions for the same but nothing works. Any help would be appreciated.
If you want the difference between two date in Hours, Minutes and seconds you can use DateComponent like this.
let component = Calendar.current.dateComponents([.hour, .minute, .second], from: Date(), to: startDate)
let hours = component.hour ?? 0
let minutes = component.minute ?? 0
let seconds = component.second ?? 0
Edit: To get date from miliseconds use Date(timeIntervalSince1970:) like this.
let startDate = Date(timeIntervalSince1970: miliSeconds / 1000)
Also you can convert string to Date using DateFormatter like this.
let stringDate = "2016-11-30 17:37:00"
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "yyyy-MM-dd HH:mm:ss"
dateFormatter.timeZone = TimeZone(abbreviation: "GMT")
if let startDate = dateFormatter.date(from: stringDate) {
print(startDate)
}
I have two times in the format HH:MM how would I compare the second from the first one finding how many minutes left until I reach to the first time:
example:
timeOne = 12:01
timeTwo = 11:32
output = 29 minutes
Any help writing this in Swift?
NSCalendar can diff dates easily (assuming start and end are NSDate instances
let calendar = NSCalendar.currentCalendar()
let components = calendar.components(.Minute, fromDate: start, toDate: end, options: [])
components.minute
If you are interested in getting just the formatted string, and not the actual value, then checkout NSDateComponentsFormatter:
let formatter = NSDateComponentsFormatter()
formatter.allowedUnits = .Minute
formatter.unitsStyle = .SpellOut
// includesTimeRemainingPhrase gives strings like "T minutes remaining"
formatter.stringFromDate(start, toDate: end)
By changing the unitsStyle, you could get different representations, such as:
"54m"
"54 minutes"
"54 min"
"fifty-four minutes"
You should operate with 2 NSDate instances, then you may use next API:
let interval = laterDate.timeIntervalSinceDate(earlierDate)
It returns the number of seconds, as an NSTimeInterval value.
Divide it by 60 will give you minutes.
so i am making a basic week picker, where you can pick a week number and year, and get the corresponding date from the weeks startpoint.
A basic test scenario
let calendar = NSCalendar.currentCalendar()
let components = NSDateComponents()
components.year = 2015
components.weekOfYear = 15
print(calendar.dateFromComponents(components)!)
You can see, that i set the wanted year to 2015 and the wanted week to 15, but the result i get is: "2014-12-31 23:00:00 +0000"
... and thats really gets me hanging. No matter what week and year i choose, it will always be off and in december.
Thank you in advance for your help.
weekOfYear works in conjunction with yearForWeekOfYear:
let calendar = NSCalendar.currentCalendar()
let components = NSDateComponents()
components.yearForWeekOfYear = 2015
components.weekOfYear = 15
print(calendar.dateFromComponents(components)!)
// 2015-04-05 22:00:00 +0000
Update for Swift 3 and later:
let calendar = Calendar.current
var components = DateComponents()
components.yearForWeekOfYear = 2015
components.weekOfYear = 15
print(calendar.date(from: components)!)