Human Readable File Size & Duration
Here's a little Objective-C code for creating a human-readable file size given a quantity of bytes. If you're not using ARC this'll leak memory.
It's roughly modeled off the behavior of the Finder - that is, no more than two decimal places; powers of ten instead of powers of two. Also it loses a little precision. I'll update this later after I've improved it - later.
+ (NSString *)humanReadableFileSize:(unsigned long long)fileSize
{
static unsigned long long tb = 1000ULL * 1000ULL * 1000ULL * 1000ULL;
static unsigned long long gb = 1000ULL * 1000ULL * 1000ULL;
static unsigned long long mb = 1000ULL * 1000ULL;
static unsigned long long kb = 1000ULL;
unsigned long long divisor = 0;
NSString *magnitude = nil;
if (fileSize == 0)
return @"Zero bytes";
else if (fileSize > tb) {
divisor = tb;
magnitude = @"TB";
}
else if (fileSize > gb) {
divisor = gb;
magnitude = @"GB";
}
else if (fileSize > mb) {
divisor = mb;
magnitude = @"MB";
}
else if (fileSize > kb) {
divisor = kb;
magnitude = @"KB";
}
else
return [NSString stringWithFormat:@"%llu bytes", fileSize];
unsigned long long whole = (fileSize / divisor);
unsigned long long part = (fileSize - (whole * divisor)) / (divisor / 1000);
unsigned long long tenths = part / 100;
unsigned long long hundredths = (part - (tenths * 100)) / 10;
NSMutableString *fileSizeStr = [[NSMutableString alloc] init];
[fileSizeStr appendFormat:@"%llu", whole];
if (tenths) {
[fileSizeStr appendString:@"."];
[fileSizeStr appendFormat:@"%llu", tenths];
if (hundredths)
[fileSizeStr appendFormat:@"%llu", hundredths];
}
else if (hundredths) {
[fileSizeStr appendString:@".0"];
[fileSizeStr appendFormat:@"%llu", hundredths];
}
[fileSizeStr appendString:@" "];
[fileSizeStr appendString:magnitude];
return fileSizeStr;
}
Along the same lines, given a duration in milliseconds (the first function) or a start and end time as timevals (the second function), these will create an hh:mm:ss.sss formatted string.
+ (NSString *)durationInMillisecondsToTime:(int64_t)duration
{
NSInteger hours=0, minutes=0, seconds=0, millis=0;
if (duration > 3600000L) {
hours = duration / 3600000L;
duration -= (hours * 3600000L);
}
if (duration > 60000L) {
minutes = duration / 60000L;
duration -= (minutes * 60000L);
}
if (duration > 1000L) {
seconds = duration / 1000L;
duration -= (seconds * 1000L);
}
millis = duration;
return [NSString stringWithFormat:@"%02d:%02d:%02d.%d", hours, minutes, seconds, millis];
}
+ (NSString *)durationFrom:(struct timeval)tv1 until:(struct timeval)tv2
{
int64_t beg, end;
beg = (int64_t)tv1.tv_sec * 1000000L;
beg += tv1.tv_usec;
end = (int64_t)tv2.tv_sec * 1000000L;
end += tv2.tv_usec;
return [self durationInMillisecondsToTime:(end-beg)/1000L];
}