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];
}

Subscribe to A garage sale for your mind

Don’t miss out on the latest posts. Sign up now to get access to the library of members-only posts.
[email protected]
Subscribe