How can I format time intervals in Cocoa? - cocoa

I'm looking for a class that formats time intervals like this:
1 hour 3 minutes
2 hours 5 minutes 12 seconds
5 days 2 hours
Is there anything built-in or a library that supports this kind of time interval formatting?
I thought about doing it myself, but there are all sorts of problems:
Localization
Non-gregorian calendars.

An old question, but for anyone who stumbles on this, check out NSDateComponentsFormatter.
For example, here's a NSDate category method from my DejalFoundationCategories open source project:
+ (NSString *)dejal_relativeStringForTimeInterval:(NSTimeInterval)timeInterval style:(NSDateComponentsFormatterUnitsStyle)unitsStyle maximumUnits:(NSInteger)maximumUnits keepZero:(BOOL)keepZero defaultValue:(NSString *)defaultValue;
{
// If more than 10 years, assume distant past or future:
if (abs(timeInterval) > 60 * 60 * 24 * 365 * 10)
{
return defaultValue;
}
NSDateComponentsFormatter *formatter = [NSDateComponentsFormatter new];
formatter.unitsStyle = unitsStyle;
formatter.maximumUnitCount = maximumUnits;
if (keepZero)
{
formatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorDropLeading | NSDateComponentsFormatterZeroFormattingBehaviorDropMiddle;
}
else
{
formatter.zeroFormattingBehavior = NSDateComponentsFormatterZeroFormattingBehaviorDropAll;
}
return [formatter stringFromTimeInterval:timeInterval];
}

Related

DHTMLX Scheduler custom Timeline with AM/PM days

I use the DHTMLX Scheduler in Timeline view for a project and the working hours are from 7AM to 5PM. I was able to make an AM/PM view per day but the first_hour and last_hour configs are not respected in the view. The screenshot shows more. The first event in the morning should be displayed far more left as it starts at 7:30Am.
My config:
scheduler.locale.labels.timeline_tab = "Timeline";
scheduler.locale.labels.section_custom = "Section";
scheduler.config.dblclick_create = false;
scheduler.config.edit_on_create = false;
scheduler.config.details_on_dblclick = false;
scheduler.config.details_on_create = false;
scheduler.config.start_on_monday = true;
scheduler.config.first_hour = 7;
scheduler.config.last_hour = 17;
scheduler.config.full_day = true;
scheduler.config.mark_now = false;
scheduler.config.drag_move = false;
scheduler.config.drag_resize = false;
//===============
//Configuration
//===============
scheduler.createTimelineView({
name: "timeline",
x_unit: "hour",
x_date: "%A",
x_step: 12,
x_size: 14,
x_start: 0,
x_length: 14,
y_unit: scheduler.serverList('teams'), // sections and events from same ajax call
y_property: "team_id",
render: "bar",
section_autoheight: false,
dy: 30,
dx: 100,
// first_hour: 7,
// last_hour: 17,
second_scale: {
x_unit: "day", // unit which should be used for second scale
x_date: "%D %j %M"
}
});
Any help will be appreciated.
EDIT:
After update based on the answer here the result:
first_hour, last_hour configs applied for Y-axis in Day, Week, Units views (check Documentation).
Currently, to hide hours at the beginning and end of the day in the Timeline view, you should have only 1 X-axis like in this sample. I.e. visible part of the event is from 10 to 18 because of first_hour, end_hour properties of createTimelineView method. Check the screenshot.
There is also ignore_[viewName] function which can be used to hide interval that equal to min step of the scale (12 hours in your case).
This could help solve your issue if set min step = 6 (hours) and disable 6-7 AM and 5-6 PM by addMarkedTimespan. I tried to create a snippet for you http://snippet.dhtmlx.com/46ba545ad , but found out that the second part of this condition if(date.getHours() < 6 || date.getHours() > 17){ is not working correctly. The event can be created until 6 PM. We will fix it ASAP, but now I can't specify the exact time. I suggest you use the first way with 1 scale to solve the issue.

How to make UIImage move every hour?

Hey so I'm working on a simple app and I want this image on a map to move closer hour by hour towards the user location. I can't figure out where to start, can anyone help?
Thanks!
Swift has a Timer class. There are several overloads for Timer.init. The newer block based one works like this:
let hour = TimeInterval(60 * 60) //60 seconds per min * 60 min per hour = 360 seconds per hour
let timer = Timer.init(timeInterval: hour, repeats: true) { timer in
//Do hourly update stuff here
}

Swift 2 get minutes and seconds from double

I am currently storing time in seconds (for example 70.149 seconds). How would I easily get the minutes and seconds? What I mean is 70.149 seconds is 1min and 10sec. How would I be able to do this easily in swift?
Here is an example of what I want to do.
let time:Double = 70.149 //This can be any value
let mins:Int = time.minutes //In this case it would be 1
let secs:Int = time.seconds //And this would be 10
How would I do this using Swift 2 OS X (not iOS)
Something like this:
let temp:Int = Int(time + 0.5) // Rounding
let mins:Int = temp / 60
let secs:Int = temp % 60
This would be a relatively simple solution. It's worth noting this would truncate partial seconds. You'd have to use floating point math on the third line and call trunc()/ceil()/floor() on the result before conversion to an Int if you wanted control over that.
let time:Double = 70.149 //This can be any value
let mins:Int = Int(time) / 60 //In this case it would be 1
let secs:Int = Int(time - Double(mins * 60)) //And this would be 10
Swift 5
The date components formatter has lots of advantages when displaying human readable text to a user. This function will take a double.
func humanReadable(time:Double) -> String {
let formatter = DateComponentsFormatter()
formatter.allowedUnits = [.hour, .minute, .second]
formatter.unitsStyle = .full
if let str = formatter.string(from: time) {
return str
}
return "" // empty string if number fails
}
// will output '1 minute, 10 seconds' for 70.149

Replacing NSDate value if two NSDate objects aren't equal

basically I'm writing an app and I want some of its values to update weekly - so, using NSDate and NSUserDefaults I currently have this scenario set out:
let userDefaults = NSUserDefaults.standardUserDefaults()
var startOfWeek: NSDate?
The above is global^
var referenceDate = NSDate.timeIntervalSinceReferenceDate()
while referenceDate > 604800 {
if referenceDate > 604800 {
referenceDate -= 604800
}
This basically takes the amount of seconds that have elapsed since the 1st of Jan 2001 and subtracts 604800, which is the amount of seconds in a week, until you have an amount of seconds that is less than a week. This amount of seconds is basically the amount of seconds into the week, you're in.
After this I then create a variable which is just the negative of how many seconds into the week we are, a variable which is the current time and use them to create a new date object which is the start point for the week:
var weekTimer: NSTimeInterval = (-referenceDate)
var startOfWeek = userDefaults.objectForKey("startOfWeekKey") as? NSDate
var currentTime = NSDate(timeIntervalSinceNow: 0)
if startOfWeek == nil {
startOfWeek = NSDate(timeInterval: weekTimer, sinceDate: currentTime)
userDefaults.objectForKey("startOfWeekKey")
}
else {
}
So basically it creates a value for the start of the week and saves it to NSUserDefaults under the key "startOfWeekKey" if the value doesn't already exist. If the value does already exist, because it's already been saved, it's happy with this value and nothing happens.
Now, we create a new value to compare to our startOfWeek value so we can test if we enter a new week.
var startOfWeekCheck = NSDate(timeInterval: weekTimer sinceDate: currentTime)
Now we compare them:
if startOfWeek! == startOfWeekCheck {
}
else {
println("New week begins") //update other, irrelevant stuff here
startOfWeek = startOfWeekCheck
}
No matter what, new week begins is always printed, I added the following line to check what was happening:
println("\(startOfWeek!) \(startOfWeekCheck)")
And it prints the same value to the logs
I'm pretty unsure what to do at this point. Did I mess up? Can you not compare the two date objects like that? Is this a ridicuously inefficient manner to create a way to reset/change something once a week?
Note, this is not the exact code, I typed this all by hand because the code is on my macbook and I'm on my desktop, so if there are any typos / w/e don't worry about it, no compile errors on my mac.
Thanks!
This looks way too complicated. There is no need to do all the date calculations yourself. Especially because you do them wrong. Not every week has 604800 seconds. In many timezones you have one week per year which has 601200 seconds, and one week which has 608400 seconds. Also known as Daylight saving time. There are even countries that skipped a whole day in one year.
You have to use NSCalendar and NSDateComponents for correct date calculations.
But I would do it completely different:
Save the next refresh date in NSUserDefaults (default to distantPast)
If today >= next refresh date: refresh & write new refresh date.
Something like this:
let calendar = NSCalendar.currentCalendar()
// If nextRefreshDate was never written by us (i.e. first start of app) it will containt distantPast, which is in year 1 or so
NSUserDefaults.standardUserDefaults().registerDefaults(["nextRefreshDate" : NSDate.distantPast()])
// since we registered a default value we will always receive a valid NSDate object, so we can force unwrap
let nextRefreshDate = NSUserDefaults.standardUserDefaults().objectForKey("nextRefreshDate") as NSDate
// equivalent to: (nextRefreshDate < today) || (nextRefreshDate == today)
if nextRefreshDate.compare(NSDate()) != NSComparisonResult.OrderedDescending {
println("Refresh")
let refreshSuccess = true // get from your internet download code
if refreshSuccess {
// don't save the next refresh date until the refresh was actually sucessful. This makes sure that we refresh on next launch if this refresh fails for some reason
var startOfCurrentWeek: NSDate?
if calendar.rangeOfUnit(.CalendarUnitWeekOfMonth, startDate: &startOfCurrentWeek, interval: nil, forDate: NSDate()) {
if let startOfCurrentWeek = startOfCurrentWeek {
if let startOfNextWeek = calendar.dateByAddingUnit(.CalendarUnitWeekOfMonth, value: 1, toDate: startOfCurrentWeek, options: nil) {
NSUserDefaults.standardUserDefaults().setObject(startOfNextWeek, forKey: "nextRefreshDate")
println("Next refresh scheduled for \(startOfNextWeek)")
}
}
}
}
}
else {
println("No refresh necessary. Next refresh scheduled for \(nextRefreshDate)")
}

how to find time difference in titanium

I am new to titanium.
I want to find time difference in titanium. Ex 12.00 AM- 12.00 PM should give me 12 hours.
But I'm not able to get how to find it in titanium.
I'm trying
function calculatetime(chkintime,chkouttime)
{
var difference = chkintime - chkouttime;
Ti.API.info(':'+difference);
var hoursDifference = Math.floor(difference/1000/60/60);
difference -= hoursDifference*1000*60*60
var minutesDifference = Math.floor(difference/1000/60);
difference -= minutesDifference*1000*60
Ti.API.info(':'+hoursDifference);
Ti.API.info(':'+minutesDifference);
var time=hoursDifference+':'+minutesDifference;
return time;
}
It sometimes gives correct answer while sometimes negative values.
here chkintime and chkouttime values are in miliseconds e.g. 1355495784321
It's no different from finding a time difference in JavaScript. (In fact, it is finding a time difference in JavaScript.)
Check time difference in Javascript
Past that, a nice way to calculate the number of days between X and Y is to find out the MS difference, then add that time to a set date, like January 1st, 2000. Then you can really easily pull the number of years, months, days, hours, minutes, and seconds. There will be some inaccuracy caused by leap years, but if you're dealing with small period, it doesn't matter at all.
var start = new Date('February, 22, 2011 2:00 PM');
var end = new Date('February, 22, 2011 4:00 PM');
var ms = end - start;
var niceDate = new Date(new Date('January 1, 2000').getTime() + ms);
var years = niceDate.getFullYear() - 2000;
var months = niceDate.getMonth();
var days = niceDate.getDate();
var hours = niceDate.getHours();
var minutes = niceDate.getMinutes();
var seconds = niceDate.getSeconds();
alert(years + ' years,\n'
+ months + ' months,\n'
+ days + ' days,\n'
+ hours + ' hours,\n'
+ minutes + ' min,\n'
+ seconds + ' sec');

Resources