Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

TimeInterval's in() function must accept or not a reference date #505

Closed
ernestofndz opened this issue Nov 7, 2017 · 3 comments
Closed
Assignees
Labels
Milestone

Comments

@ernestofndz
Copy link

ernestofndz commented Nov 7, 2017

Hey guys, amazing work, love it.

I've got a weird behaviour when comparing dates. I'm running the latest version at this moment which is 4.4.2

screen shot 2017-11-07 at 19 17 41

Date base that I'm using to compare
2017-11-21 00:00:00 +0000 timeIntervalSince1970 = 1511222400.0

Against
2017-11-30 00:00:00 +0000 timeIntervalSince1970 = 1512000000.0
difference in seconds is 777600 which in days is 9
SwiftDate says 9

Against
2017-12-01 00:00:00 +0000 timeIntervalSince1970 = 1512086400.0
difference in seconds is 864000 which in days is 10
SwiftDate says 9

Dates going forward are also calculated wrong. Any ideas?

@malcommac
Copy link
Owner

Hi @ernestofndz , may I ask to post the code used for these test here so I can make further investigations? Thanks

@ernestofndz
Copy link
Author

Hi @malcommac, I just created a sample project: https://github.com/ernestofndz/SDDateDiff.

The code in the AppDelegate makes no difference, but just keeping it as I have in the other project. If I get some time this weekend will try to take a look myself. Thanks!

@malcommac
Copy link
Owner

malcommac commented Nov 26, 2017

Thank you for your report.
Function return wrong values because conversion take care of the interval starting from a specific date (specifically range used by the function is {Date() - Date() - interval}).
I've modified the function to allow passing a start reference date.
If date is passed conversion take care of this value.
If date is not passed conversion is absolute but only a small subset of time components are accepted (.day,.hour,.minute,.second).

/// Express given time interval in other time units.
/// If a reference date (`fromDate`) is not specified conversion is aware of day light saving times and other possible nasty things
/// (only `.day,.hour,.minute,.second` are supported as components).
/// If a reference date is specified conversion is made using the interval from passed reference date and include calendar/date
/// specific events.
///
///
/// - Parameters:
///   - components: components to extract
///   - date: reference date; `nil` uses absolute conversion, valida date to set the interval from a specific date.
///   - calendar: context calendar; `nil` uses `Date.DefaultRegion.calendar` instead
/// - Returns: components
public func `in`(_ components: [Calendar.Component], fromDate date: Date? = nil, of calendar: Calendar? = nil) -> [Calendar.Component : Int] {
	guard let refDate = date else {
			// Absolute conversion, not taking care of specific starting date
		let days = Int( (components.contains(.day) ? self / (60 * 60 * 24) : 0) )
		let hours = Int((components.contains(.hour) ? ((self / (60 * 60)) - (Double(days) * 24)) : 0))
		let minutes = Int( (components.contains(.minute) ? ((self / 60) - (Double(days) * 24 * 60) - (Double(hours) * 60)) : 0))
		let seconds = Int( (components.contains(.second) ? (self - (Double(days) * 24 * 60) - (Double(hours) * 60 * 60) - Double(minutes) * 60) : 0))
			
		var components: [Calendar.Component : Int] = [:]
		if (days != 0) 		{ components[.day] = Int(days) }
		if (hours != 0) 	{ components[.hour] = Int(hours) }
		if (minutes != 0)	{ components[.minute] = Int(minutes) }
		if (seconds != 0)	{ components[.second] = Int(seconds) }
		return components
	}
		
	let cal = calendar ?? Date.defaultRegion.calendar
	let dateFrom: Date = refDate
	let dateTo: Date = dateFrom.addingTimeInterval(self)
	let cmps = cal.dateComponents(componentsToSet(components), from: dateFrom, to: dateTo)
	return cmps.toComponentsDict()
}

@malcommac malcommac changed the title Difference between dates is incorrect TimeInterval's in() function must accept or not a reference date Nov 26, 2017
@malcommac malcommac added the bug label Nov 26, 2017
@malcommac malcommac added this to the 4.5.0 milestone Nov 26, 2017
@malcommac malcommac self-assigned this Nov 26, 2017
malcommac added a commit that referenced this issue Nov 26, 2017
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants