将 NSDate 舍入到最接近的 5 分钟
例如我有
NSDate *curDate = [NSDate date];
,它的值是上午 9:13。 我没有使用 curDate 的年、月和日部分。
我想要得到的是时间值为 9:15 的日期; 如果我的时间值为 9:16,我想将其提前到 9:20,依此类推。
我怎样才能用 NSDate 做到这一点?
For example I have
NSDate *curDate = [NSDate date];
and its value is 9:13 am. I am not using year, month and day parts of curDate.
What I want to get is date with 9:15 time value; If I have time value 9:16 I want to advance it to 9:20 and so on.
How can I do that with NSDate?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(19)
另一种 Swift 通用解决方案,使用 NSCalendar 最多可进行 30 分钟的舍入
One more Swift generic solution, which works up to 30 minutes rounding using NSCalendar
我自己一直在寻找这个,但是使用上面的例子给了我从 0001 年开始的日期。
这是我的替代方案,结合了 smorgan 更优雅的模组建议,但请注意我还没有对此进行泄漏测试:
Had been looking for this myself, but using the example above gave me from year 0001 dates.
Here's my alternative, incorporated with smorgan's more elegant mod suggestion though beware I haven't leak tested this yet:
我将 @J3RM 的解决方案重写为 Swift 中 NSDate 类的扩展。 这里是将日期四舍五入到最接近的 15 分钟间隔:
I rewrote @J3RM 's solution as an extension in Swift on the NSDate class. Here it is for rounding a date to the nearest 15th minute interval:
我不确定 NSDateComponents 的效率如何,但如果您只想处理 NSDate 本身,它可以为您提供基于秒的值,然后可以对其进行操作。
例如,此方法向下舍入到最接近的分钟。 将 60 更改为 300,它将向下舍入到最接近的 5 分钟。
I'm not sure how efficient NSDateComponents are, but if you just want to deal with the NSDate itself it can give you values based on seconds which can then be manipulated.
For example, this method rounds down to the nearest minute. Change the 60 to 300 and it will round down to nearest 5 minutes.
这是一个通用的解决方案,它四舍五入到最接近的输入“分钟”:
This is a generic solution which rounds up to the nearest input 'mins':
甚至更短......限制为秒:
Even shorter... limit to seconds:
这是我的解决方案:
我做了一些测试,它的速度大约是沃斯解决方案的十倍。 1M 次迭代大约需要 3.39 秒。 这一次的表演时间为 0.38 秒。 J3RM的解决方案花费了0.50秒。 内存使用率也应该是最低的。
并不是说性能就是一切,但它只是一句台词。 您还可以轻松控制除法和乘法的舍入。
编辑:要回答这个问题,您可以使用 ceil 来正确舍入:
编辑:Swift 中的扩展:
Here's my solution:
I did some testing and it is about ten times as fast as Voss's solution. With 1M iterations it took about 3.39 seconds. This one performed in 0.38 seconds. J3RM's solution took 0.50 seconds. Memory usage should be the lowest also.
Not that the performance is everything but it's a one-liner. Also you can easily control the rounding with division and multiplication.
EDIT: To answer the question, you can use
ceil
to round up properly:EDIT: An extension in Swift:
取分钟值,除以 5 向上舍入以获得下一个最高的 5 分钟单位,乘以 5 得到以分钟为单位的值,并构造一个新的 NSDate。
Take the minute value, divide by 5 rounding up to get the next highest 5 minute unit, multiply to 5 to get that back into in minutes, and construct a new NSDate.
基于 Chris 和 swift3 的这个怎么样?
How about this based on Chris' and swift3
Wowsers,我在这里看到了很多答案,但很多都很长或难以理解,所以我会尽力投入我的 2 美分,以防有帮助。 NSCalendar 类以安全且简洁的方式提供所需的功能。 这是一个适合我的解决方案,无需乘以时间间隔秒数、舍入或任何其他内容。
NSCalendar
考虑了闰日/年份以及其他时间和日期的异常情况。 (Swift 2.2)如果需要,它可以添加到 NSDate 的扩展中,或者作为返回新的 NSDate 实例的自由格式函数,无论您需要什么。 希望这可以帮助任何有需要的人。
Swift 3 更新
Wowsers, I see a lot of answers here, but many are long or difficult to understand, so I'll try to throw in my 2 cents in case it helps. The
NSCalendar
class provides the functionality needed, in a safe and concise manner. Here is a solution that works for me, without multiplying time interval seconds, rounding, or anything.NSCalendar
takes into account leap days/years, and other time and date oddities. (Swift 2.2)It can be added to an extension on
NSDate
if needed, or as a free-form function returning a newNSDate
instance, whatever you need. Hope this helps anyone who needs it.Swift 3 Update
https://forums.developer.apple.com/thread/92399
查看完整链接以及苹果工作人员的详细解答。 为了节省您的点击次数,解决方案:
https://forums.developer.apple.com/thread/92399
see link for full and detailed answer from an Apple staff member. To save you a click, the solution:
我认为这是最好的解决方案,但这只是我的观点,基于之前的海报代码。 四舍五入到最接近的 5 分钟标记。 该代码应该比日期组件解决方案使用更少的内存。 太棒了,感谢您的指导。
I think this is the best solution, but just my opinion, based on previous poster code. rounds to nearest 5 min mark. This code should use a lot less memory than the date components solutions. Brilliant, Thanks for the direction.
感谢您提供样品。
下面我在最接近的 5 分钟的回合中添加了一些代码
Thanks for the sample.
Below I have added some code the round to nearest 5 minutes
不幸的是,这里的大多数回复并不完全正确(即使它们对于大多数用户来说似乎工作得很好),因为它们要么依赖于当前活动的系统日历是公历(情况可能并非如此),要么依赖于以下事实:闰秒不存在和/或总是被 OS X 和 iOS 忽略。 下面的代码可以复制和粘贴,保证是正确的,并且它没有做出这样的假设(因此,如果苹果改变闰秒支持,将来也不会中断,因为在这种情况下,NSCalendar也必须正确支持它们) :
如果当前时间已经是5分钟的倍数,则代码不会更改它。 原来的问题没有明确说明这种情况。 如果代码始终向上舍入为下一个 5 分钟的倍数,只需删除测试
if (mines % 5) {
,它就会始终向上舍入。Most replies here are unfortunately not perfectly correct (even though they seem to work quite well for most users), as they either rely on the current active system calendar to be a Gregorian calendar (which may not be the case) or upon the fact that leap seconds don't exist and/or will always be ignored by OS X an iOS. The following code works copy&paste, is guaranteed to be correct and it makes no such assumptions (and thus will also not break in the future if Apple changes leap seconds support, as in that case NSCalendar will have to correctly support them as well):
If the current time is already a multiple of 5 minutes, the code will not change it. The original question did not specify this case explicitly. If the code shall always round up to the next multiple of 5 minutes, just remove the test
if (minutes % 5) {
and it will always round up.@ipje 的答案在接下来的 5 分钟内解决了问题,但我需要更灵活的东西,我想摆脱所有神奇的数字。
感谢对类似问题的回答,我找到了解决方案
我的解决方案使用 Swift 5.2 和
Measurement
来避免使用幻数:在我的游乐场中:
The answer from @ipje did the trick for the next 5 minutes but I needed something more flexible and I wanted to get rid of all the magic numbers.
I found a solution thanks to an answer to a similar question
My solution uses the Swift 5.2 and
Measurement
to avoid using magic numbers:In my playground :
我刚刚开始在我的一个应用程序中尝试这一点,并提出了以下建议。 它是用 Swift 编写的,但即使您不了解 Swift,这个概念也应该足够容易理解。
结果在我的操场上看起来是正确的,我在其中注入了各种自定义日期,接近午夜,接近新年等。
编辑:Swift2 支持:
I just started experimenting with this for an app of mine, and came up with the following. It is in Swift, but the concept should be understandable enough, even if you don't know Swift.
The result looks correct in my playground, where I inject various custom dates, close to midnight, close to a new year etc.
Edit: Swift2 support:
这是我使用 ayianni 的包装器思想对原始问题(向上舍入)的解决方案。
Here's my solution to the original problem (rounding up) using ayianni's wrapper idea.
我知道这是一个较旧的线程,但由于有更新的答案,我将分享我用来将 NSDate 舍入到最近的 5 分钟间隔的实用方法。
当 UITextField 成为 FirstResponder 时,我使用它来填充当前 UIDatePicker 日期。 当 UIDatePicker 配置为 1 分钟间隔以外的其他值时,您不能只使用 [NSDate date]。 我的配置为 5 分钟间隔。
忽略问题的标题并阅读 @aler 真正想要完成的任务(四舍五入到最近的 5 分钟)。 您所要做的就是以下操作:
I know this is an older thread, but since there are more recent answers I will share the utility method that I use to round an NSDate to the nearest 5 minute interval.
I use this to populate a UITextField with the current UIDatePicker date when it becomes FirstResponder. You can't just use [NSDate date] when the UIDatePicker is configured with something other than a 1 minute interval. Mine are configured with 5 minute intervals.
Ignoring the title of the question and reading what @aler really wants to accomplish (rounding UP to the nearest 5 minute). All you have to do is the following: