Code Monkey home page Code Monkey logo

formatterkit's Introduction

FormatterKit

This library is no longer being maintained. Since its initial release in 2011, Apple has filled in many of the gaps FormatterKit was created to fill in Foundation and other SDK frameworks:

Deprecated FormatterKit API Apple SDK API Availability
TTTAddressFormatter CNPostalAddressFormatter iOS 9.0+ / macOS 10.11+
TTTArrayFormatter NSListFormatter iOS 13.0+ / macOS 10.15+
TTTNameFormatter NSPersonNameComponentsFormatter iOS 9.0+ / macOS 10.11+
TTTLocationFormatter NSMeasurementFormatter + NSUnitDistance / NSUnitAngle iOS 10.0+ / macOS 10.12+
TTTOrdinalNumberFormatter NSNumberFormatter + NSNumberFormatterOrdinalStyle iOS 9.0+ / macOS 10.11+
TTTTimeIntervalFormatter NSRelativeDateTimeFormatter iOS 13.0+ / macOS 10.15+
TTTUnitOfInformationFormatter NSMeasurementFormatter + NSUnitInformationStorage iOS 13.0+ / macOS 10.15+

You can continue to use FormatterKit in your projects, but we recommend switching to the corresponding Apple APIs as soon as it makes sense to do so.

Going forward, we plan to spin out non-deprecated formatters into their own repositories for future development as well as any new projects. This repository will remain archived here for compatibility with existing installations.


FormatterKit is a collection of well-crafted NSFormatter subclasses for things like units of information, distance, and relative time intervals. Each formatter abstracts away the complex business logic of their respective domain, so that you can focus on the more important aspects of your application.

In short, use this library if you're manually formatting any of the following (with string interpolation or the like):

  • Addresses: Create formatted address strings from components (e.g. 221b Baker St / Paddington / Greater London / NW1 6XE / United Kingdom )
  • Arrays: Display NSArray elements in a comma-delimited list (e.g. "Russell, Spinoza & Rawls")
  • Colors: RGB, CMYK, and HSL your ROY G. BIV in style. (e.g. #BADF00D, rgb(255, 100, 42))
  • Location, Distance & Direction: Show CLLocationDistance, CLLocationDirection, and CLLocationSpeed in metric or imperial units (eg. "240ft Northwest" / "45 km/h SE")
  • Names: Display personal names in the correct format, according to the current locale and source language (eg. "山田花子" for the Japanese first name "花子" (Hanako) and last name "山田" (Yamada))
  • Ordinal Numbers: Convert cardinal NSNumber objects to their ordinal in most major languages (eg. "1st, 2nd, 3rd" / "1ère, 2ème, 3ème")
  • Time Intervals: Show relative time distance between any two NSDate objects (e.g. "3 minutes ago" / "yesterday")
  • Units of Information: Humanized representations of quantities of bits and bytes (e.g. "2.7 MB")
  • URL Requests: Print out cURL or Wget command equivalents for any NSURLRequest (e.g. curl -X POST "https://www.example.com/" -H "Accept: text/html")

Installation

CocoaPods

You can install FormatterKit via CocoaPods, by adding the following line to your Podfile:

pod 'FormatterKit', '~> 1.9.0'

Run the pod install command to download the library and integrate it into your Xcode project.

Carthage

To use FormatterKit in your Xcode project using Carthage, specify it in Cartfile:

github "FormatterKit/FormatterKit" ~> 1.9.0

Then run the carthage update command to build the framework, and drag the built FormatterKit.framework into your Xcode project.

Demo

Build and run the FormatterKit Example project in Xcode to see an inventory of the available FormatterKit components.


TTTAddressFormatter

Address formats vary greatly across different regions. TTTAddressFormatter ties into the Address Book frameworks to help your users find their place in the world.

For example, addresses in the United States take the form:

Street Address
City State ZIP
Country

Whereas addresses in Japan follow a different convention:

Postal Code
Prefecture Municipality
Street Address
Country

Requires that the AddressBook and AddressBookUI frameworks are linked with #import statements in Prefix.pch. TTTAddressFormatter isn't available on OS X.

Example Usage

TTTAddressFormatter *addressFormatter = [[TTTAddressFormatter alloc] init];
NSLog(@"%@", [addressFormatter stringFromAddressWithStreet:street locality:locality region:region postalCode:postalCode country:country]);

TTTArrayFormatter

Think of this as a production-ready alternative to NSArray -componentsJoinedByString:. TTTArrayFormatter comes with internationalization baked-in and provides a concise API that allows you to configure for any edge cases.

Example Usage

NSArray *list = [NSArray arrayWithObjects:@"Russel", @"Spinoza", @"Rawls", nil];
TTTArrayFormatter *arrayFormatter = [[TTTArrayFormatter alloc] init];
[arrayFormatter setUsesAbbreviatedConjunction:YES]; // Use '&' instead of 'and'
[arrayFormatter setUsesSerialDelimiter:NO]; // Omit Oxford Comma
NSLog(@"%@", [arrayFormatter stringFromArray:list]); // # => "Russell, Spinoza & Rawls"

TTTColorFormatter

RGB, CMYK, and HSL your ROY G. BIV in style. TTTColorFormatter provides string representations of colors.

Example Usage

TTTColorFormatter *colorFormatter = [[TTTColorFormatter alloc] init];
NSString *RGB = [colorFormatter RGBStringFromColor:[UIColor orangeColor]];

TTTLocationFormatter

When working with CoreLocation, you can use your favorite unit for distance... so long as your favorite unit is the meter. If you want to take distance calculations and display them to the user, you may want to use kilometers instead --- or maybe even miles if you're of the Imperial persuasion.

TTTLocationFormatter gives you a lot of flexibility in the display of coordinates, distances, direction, speed, and velocity. Choose Metric or Imperial, cardinal directions, abbreviations, or degrees, and configure everything else (number of significant digits, etc.) with the associated NSNumberFormatter.

Example Usage

TTTLocationFormatter *locationFormatter = [[TTTLocationFormatter alloc] init];
CLLocation *austin = [[CLLocation alloc] initWithLatitude:30.2669444 longitude:-97.7427778];
CLLocation *pittsburgh = [[CLLocation alloc] initWithLatitude:40.4405556 longitude:-79.9961111];

Distance in Metric Units with Cardinal Directions

NSLog(@"%@", [locationFormatter stringFromDistanceAndBearingFromLocation:pittsburgh toLocation:austin]);
// "2,000 km Southwest"

Distance in Imperial Units with Cardinal Direction Abbreviations

[locationFormatter.numberFormatter setMaximumSignificantDigits:4];
[locationFormatter setBearingStyle:TTTBearingAbbreviationWordStyle];
[locationFormatter setUnitSystem:TTTImperialSystem];
NSLog(@"%@", [locationFormatter stringFromDistanceAndBearingFromLocation:pittsburgh toLocation:austin]);
// "1,218 miles SW"

Speed in Imperial Units with Bearing in Degrees

[locationFormatter setBearingStyle:TTTBearingNumericStyle];
NSLog(@"%@ at %@", [locationFormatter stringFromSpeed:25],[locationFormatter stringFromBearingFromLocation:pittsburgh toLocation:austin]);
// "25 mph at 310°"

Coordinates

[locationFormatter.numberFormatter setUsesSignificantDigits:NO];
NSLog(@"%@", [locationFormatter stringFromLocation:austin]);
// (30.2669444, -97.7427778)

TTTNameFormatter

TTTNameFormatter formats names according to the internationalization standards of the AddressBook framework, which determine, for example, the display order of names and whether or not to delimit components with whitespace.

TTTNameFormatter isn't available on OS X.

Example Usage

TTTNameFormatter *nameFormatter = [[TTTNameFormatter alloc] init];
NSString *frenchName = [nameFormatter stringFromPrefix:nil firstName:@"Guillaume" middleName:@"François" lastName:@"Antoine" suffix:@"Marquis de l'Hôpital"];
NSLog(@"%@", frenchName);
// "Guillaume François Antoine Marquis de l'Hôpital"

NSString *japaneseName = [nameFormatter stringFromFirstName:@"孝和" lastName:@""];
NSLog(@"%@", japaneseName);
// "関孝和"

TTTOrdinalNumberFormatter

NSNumberFormatter is great for Cardinal numbers (17, 42, 69, etc.), but it doesn't have built-in support for Ordinal numbers (1st, 2nd, 3rd, etc.)

A naïve implementation might be as simple as throwing the one's place in a switch statement and appending "-st", "-nd", etc. But what if you want to support French, which appends "-er", "-ère", and "-eme" in various contexts? How about Spanish? Japanese?

TTTOrdinalNumberFormatter supports English, Spanish, French, German, Irish, Italian, Japanese, Dutch, Portuguese, Simplified Chinese and Swedish. For other languages, you can use the standard default, or override it with your own. For languages whose ordinal indicator depends upon the grammatical properties of the predicate, TTTOrdinalNumberFormatter can format according to a specified gender and/or plurality.

Example Usage

TTTOrdinalNumberFormatter *ordinalNumberFormatter = [[TTTOrdinalNumberFormatter alloc] init];
[ordinalNumberFormatter setLocale:[NSLocale currentLocale]];
[ordinalNumberFormatter setGrammaticalGender:TTTOrdinalNumberFormatterMaleGender];
NSNumber *number = [NSNumber numberWithInteger:2];
NSLog(@"%@", [NSString stringWithFormat:NSLocalizedString(@"You came in %@ place!", nil), [ordinalNumberFormatter stringFromNumber:number]]);

Assuming you've provided localized strings for "You came in %@ place!", the output would be:

  • English: "You came in 2nd place!"
  • French: "Vous êtes arrivé à la 2e place !"
  • Spanish: "Usted llegó en 2.o lugar!"

TTTTimeIntervalFormatter

Nearly every application works with time in some way or another. And when we display temporal information to users, it's typically in relative terms to the present, like "3 minutes ago", "10 months ago", or "last month". TTTTimeIntervalFormatter defaults to a smart, relative display of an NSTimeInterval value, with options to extend that behavior to your particular use case.

Example Usage

TTTTimeIntervalFormatter *timeIntervalFormatter = [[TTTTimeIntervalFormatter alloc] init];
[timeIntervalFormatter stringForTimeInterval:0]; // "just now"
[timeIntervalFormatter stringForTimeInterval:-100]; // "1 minute ago"
[timeIntervalFormatter stringForTimeInterval:-8000]; // "2 hours ago"

// Turn idiomatic deictic expressions on / off
[timeIntervalFormatter stringForTimeInterval:-100000]; // "1 day ago"
[timeIntervalFormatter setUsesIdiomaticDeicticExpressions:YES];
[timeIntervalFormatter stringForTimeInterval:-100000]; // "yesterday"

// Customize the present tense deictic expression for
[timeIntervalFormatter setPresentDeicticExpression:@"seconds ago"];
[timeIntervalFormatter stringForTimeInterval:0]; // "seconds ago"

// Expand the time interval for present tense
[timeIntervalFormatter stringForTimeInterval:-3]; // "3 seconds ago"
[timeIntervalFormatter setPresentTimeIntervalMargin:10];
[timeIntervalFormatter stringForTimeInterval:-3]; // "seconds ago"

TTTUnitOfInformationFormatter

No matter how far abstracted from its underlying hardware an application may be, there comes a day when it has to communicate the size of a file to the user. TTTUnitOfInformationFormatter transforms a number of bits or bytes into a humanized representation, using either SI decimal or IEC binary unit prefixes.

Example Usage

TTTUnitOfInformationFormatter *unitOfInformationFormatter = [[TTTUnitOfInformationFormatter alloc] init];
[unitOfInformationFormatter stringFromNumberOfBits:[NSNumber numberWithInteger:416]]; // "56 bytes"

// Display in either bits or bytes
[unitOfInformationFormatter setDisplaysInTermsOfBytes:NO];
[unitOfInformationFormatter stringFromNumberOfBits:[NSNumber numberWithInteger:416]]; // "416 bits"

// Use IEC Binary prefixes (base 2 rather than SI base 10; see http://en.wikipedia.org/wiki/IEC_60027)
[unitOfInformationFormatter setUsesIECBinaryPrefixesForCalculation:NO];
[unitOfInformationFormatter stringFromNumberOfBits:[NSNumber numberWithInteger:8660]]; // "8.66 Kbit"

[unitOfInformationFormatter setUsesIECBinaryPrefixesForCalculation:YES];
[unitOfInformationFormatter setUsesIECBinaryPrefixesForDisplay:YES];
[unitOfInformationFormatter stringFromNumberOfBits:[NSNumber numberWithInteger:416]]; // "8.46 Kibit"

TTTURLRequestFormatter

NSURLRequest objects encapsulate all of the information made in a network request, including url, headers, body, etc. This isn't something you'd normally want to show to a user, but it'd be nice to have a way to make it more portable for debugging. Enter: TTTURLRequestFormatter. In addition to formatting requests simply as POST http://www.example.com/, it also generates cURL and Wget commands with all of its headers and data fields intact to debug in the console.

Example Usage

NSMutableURLRequest *request = [[NSMutableURLRequest alloc] initWithURL:[NSURL URLWithString:@"http://www.example.com/"]];
[request setHTTPMethod:@"POST"];
[request addValue:@"text/html" forHTTPHeaderField:@"Accept"];
[TTTURLRequestFormatter cURLCommandFromURLRequest:request];
curl -X POST "https://www.example.com/" -H "Accept: text/html"

Localizations

FormatterKit comes fully internationalized, with .strings files for the following locales:

  • Catalan (ca)
  • Chinese (Simplified) (zh_Hans)
  • Chinese (Traditional) (zh_Hant)
  • Czech (cs)
  • Danish (da)
  • Dutch (nl)
  • English (en)
  • French (fr)
  • German (de)
  • Greek (el)
  • Hebrew (he)
  • Hungarian (hu)
  • Indonesian (id)
  • Italian (it)
  • Korean (ko)
  • Norwegian Bokmål (nb)
  • Norwegian Nynorsk (nn)
  • Polish (pl)
  • Portuguese (Brazilian) (pt_BR)
  • Russian (ru)
  • Spanish (es)
  • Swedish (sv)
  • Turkish (tr)
  • Ukranian (uk)
  • Vietnamese (vi)

License

FormatterKit is available under the MIT license. See the LICENSE file for more info.

formatterkit's People

Contributors

0xced avatar bcapps avatar bejo avatar bizz84 avatar defragged avatar flambert avatar hectr avatar hezi avatar imaks avatar lascorbe avatar macmannes avatar mattbischoff avatar mattt avatar michael-patzer avatar mjasa avatar mtaufen avatar otaran avatar paulbruneau avatar pfandrade avatar plaetzchen avatar rickytan avatar runmad avatar scraton avatar skywinder avatar tevelee avatar tewha avatar thomasguenzel avatar tomaz avatar verges avatar yas375 avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

formatterkit's Issues

Lack of rounding in TTTTimeInterval gives inaccurate results

I have a bunch of exact NSTimeInterval values in my app that I'd like to use FormatterKit's TTTTimeIntervalFormatter to display. Unfortunately, if I call

TTTTimeIntervalFormatter *testTimeFormatter = [TTTTimeIntervalFormatter new];
NSString *formattedTime= [testTimeFormatter stringForTimeInterval:-11*60*60];

I get "10 hours ago". Which is obviously off by an entire hour!

I just started looking at FormatterKit today, so I'm sorry if I'm using something poorly, but I've taken a look and it looks like this is caused by a lack of rounding in - stringForTimeIntervalFromDate:toDate and the fact that -stringForTimeInterval:seconds' just passes now and a date calculated using dateWithTimeIntervalSinceNow.

dateWithTimeIntervalSinceNow introduces a small rounding error with the few microseconds it takes to calculate the dates. In my test run with the values above I ended up with a value of 39599.999976 seconds rather 396000. Which causes the date components to be then broken down to 10 hours 59 minutes and 59.999976 seconds. Which wouldn't be a big deal, except that there is no rounding when the method loops through the components. Once it parses out the 10 hours (with the default values for TTTTimeIntervalFormatter) it declares itself done.

In my use case, I could probably just pass in an extra second every time I call this. (The localization and configurability of TTTimeFormatter makes this better than what I'm using, even with this issue.) But rounding seems important to me regardless. 10 hours and 55 minutes seems like it should get formatted to "about 11 hours" and that's going to occur in lots of places.

I'd be happy to write a patch to add rounding (and a property to enable/disable it). But given how long this library has been around, and how popular it is, I find it hard to believe that this hasn't be considered before. (I tried to search and see.) If this is a design decision on your part, could you help me understand? Or is there something I'm missing the library's proper use?

traditionally formatted latitude/longitude

Currently, -stringFromCoordinate: returns a parenthesized string, with west/south longitude/latitude shown as negative numbers, e.g. (48.331, -122.45). I need a format that would be used in traditional cartography, with hemisphere indicated by a letter, and minutes (and perhaps seconds) displayed instead of decimal degrees. I'd also like to lose the parentheses, e.g.
N 48° 19.9', W 122° 27.0'
or even N 48° 19' 51.6", , W 122° 27' 00.0"
I can imagine some folks might want decimal degrees, but symbolic hemispheres:
N 48.331° W 122.45°

I started to implement this as a modification to -stringFromCoordinate:, but it looks like a general solution will require three new methods. I'm thinking -degreesStringFromCoordinate:, -degreesMinutesStringFromCoordinate:, and -degreesMinutesSecondsStringFromCoordinate would be the right names. Then -stringFromCoordinate:'s behavior doesn't change.

Incorrect result for time format?

Feeling a little crazy right now, but when comparing 2 dates which are 57 days away I get "1 month 5 days" as the result

NSDateFormatter *dateFormat = [[NSDateFormatter alloc] init];
dateFormat.dateFormat = @"yyyyMMdd";
TTTTimeIntervalFormatter *timeIntervalFormatter = [[TTTTimeIntervalFormatter alloc] init];
timeIntervalFormatter.numberOfSignificantUnits = 0;
NSLog(@"%@", [timeIntervalFormatter stringForTimeIntervalFromDate:[dateFormat dateFromString:@"20130716"] toDate:[dateFormat dateFromString:@"20130911"]]);

Russian / plural forms support

Hi,

Our iOS app uses FormatterKit and we're in the process of localizing it to Russian. As you may know, pluralization rules in Russian go beyond the simple distinction between one and many – there's a form that should apply to 'few' (~ 2, 3). We're getting the messages translated right now and this is a point of contention with our translators.

Could you add support for multiple plural forms and, more broadly, for Russian in FormatterKit?

For the record, we're also getting FormatterKit messages translated in several other languages, including Japanese and Chinese. Ultimately, we'd like to channel those translations (currently in our fork) back to your project but I'm assuming engineering work is needed to actually make the formatters use these.

Pod pre_install locale script modifies other pods as well

I noticed this commit: mattt@b87e10e
I would suggest adding a filter to only remove folders of the FormatterKit pod:

pre_install do |installer|
    supported_locales = ['base', 'da', 'en']

    installer.pods.each do |pod|
        if (pod.name == 'FormatterKit')
            Dir.glob(File.join(pod.root, '**', '*.lproj')).each do |bundle|
                if (!supported_locales.include?(File.basename(bundle, ".lproj").downcase))
                    puts "Removing #{bundle}"
                    FileUtils.rm_rf(bundle)
                end
            end
        end
    end
end

In my project it started deleting folders of the CocoaLumberjack pod. Even worse it removed "English" because it didn't match "en".

Setting locale for FormatterKit has no effect

I am trying to ignore the current system locale by setting locale manually, however the locale always defaults to the current system locale. Is it a bug or it is not supposed to work like this? I assumed it should work as the property is public and writeable.

TTTTimeIntervalFormatter *timeIntervalFormatter = [[TTTTimeIntervalFormatter alloc] init];
NSLocale *locale = [NSLocale localeWithLocaleIdentifier:MyChosenLocaleIdentifier];
[timeIntervalFormatter setLocale:locale];

TTTLocationFormatter should accept an NSLocale

I think that it will be more appropriate and consistent for the TTTLocationFormatter to accept an NSLocale instead of specify an unit with an TTTLocationUnitSystem.

We can use the NSLocaleUsesMetricSystem key of NSLocale to know which unit system use plus we can use this NSLocale to set up NSNumberFormatter. For me make more sense set an NSLocale and have both the number and the unit formatted according to this locale

I'm more than happy to do this change but I want to discuss this before. What you think about it? Make sense? If yes, how we will deal with the unitSystem?

Keys reused for localization

A number of keys used by TTTTimeIntervalFormatter are used multiple times for different purposes. They need to be replaced with independent keys so languages where the value is different can be supported.

Warning: Key "day" used with multiple comments "Day Unit (Singular, Abbreviated)" & "Day Unit (Singular)"
Warning: Key "days" used with multiple comments "Day Unit (Plural, Abbreviated)" & "Day Unit (Plural)"
Warning: Key "s" used with multiple comments "Second Unit (Plural, Abbreviated)" & "Second Unit (Singular, Abbreviated)"

TTTUnitOfInformationFormatter: Use doubleValue instead of [number integerValue] to calculate prefix when self.displaysInTermsOfBytes is YES?

In -[TTTUnitOfInformationFormatter stringFromNumberOfBits:] the prefix to use for the unit string is calculated using the number parameter irrespective of whether self.displaysInTermsOfBytes is set.

For example, if number is 1,600,000 bits and self.displaysInTermsOfBytes is not set the resulting string will be "1.6Mbit" which makes sense.

If number is 1,600,000 bits and self.displaysInTermsOfBytes is set the resulting string will be "0.2MB" rather than "200KB". Is this desirable behavior?

It seems to me that if self.displaysInTermsOfBytes is set the user would prefer the prefix to match the number of bytes rather than the number of bits.

Thoughts?

TTAddressFormatter from cocoapods

Compiler won't find TTTAddressFormatter if the class comes from a pod, (it works copying the file in the project). I tried to fix it adding ''AddressBookUI'' to the subspec.frameworks but no luck.

projects .pch includes (inside #ifdef OBJC):

   #ifdef __IPHONE_OS_VERSION_MIN_REQUIRED
        #import <AddressBook/AddressBook.h>
        #import <AddressBookUI/AddressBookUI.h>
   #endif

Build error:

"OBJC_CLASS$_TTTAddressFormatter", referenced from:
objc-class-ref in XFDVenueParser.o
ld: symbol(s) not found for architecture armv7s

Any ideas?

Thanks!

The use of @"%@ %@" for dimensional, distance, speed and deictic expression breaks for french

@"%@ %@" is used for all of them as a key, but in french, you'd want "il y a 3s" and "8 km", but you will either get "3s il y a" or "km 8" depending of if you switch the parts around or not.

/* #{Dimensional Quantity} #{Direction}
#{Distance} #{Unit}
#{Speed} #{Unit}
Deictic Expression Format (#{Time} #{Ago/From Now} */
"%@ %@" = "%1$@ %2$@"; // "3s il y a" and "8 km"
"%@ %@" = "%2$@ %1$@"; // "il y a 3s" and "km 8"

Incorrect version of podspec in Cocoapods repo

If you look at the version of the podspec tagged as 1.2, you'll see that it does not include the localization resources anywhere (either in the main project or the sub projects). The latest version correctly has the localization resource lines. Please move the 1.2.0 tag to the latest podspec version.

Actually upon further inspection it is the podspec in the Cocoapods repo that is incorrect.

enRelativeDateStringForComponents returns 'yesterday' incorrectly

I have a date that is 2 months, 2 weeks and 1 day in the past, and the method "enRelativeDateStringForComponents" in TTTTimeIntervalFormatter.m returns "yesterday".

The check on line 195 is this:
} else if ([components day] == -1) {

I think it needs to also check that year/month/week are 0, like this:

} else if (([components day] == -1) && ([components year] == 0) && ([components month] == 0) && ([components week] == 0)) {

The same needs to apply to the checks for:

  • week (line 193 - needs to check if month and years are 0)
  • month (line 191 - needs to check if year is 0)

LocalizedStringKey "day" in TTTTimeIntervalFormatter used twice

The - (NSString *)localizedStringForNumber:(NSUInteger)number ofCalendarUnit:(NSCalendarUnit)unit implementation uses the same LocalizedString key for day in abbreviated and full.

return singular ? NSLocalizedStringFromTable(@"day", @"FormatterKit", @"Day Unit (Singular, Abbreviated)") : NSLocalizedStringFromTable(@"days", @"FormatterKit", @"Day Unit (Plural, Abbreviated)");
return singular ? NSLocalizedStringFromTable(@"day", @"FormatterKit", @"Day Unit (Singular)") : NSLocalizedStringFromTable(@"days", @"FormatterKit", @"Day Unit (Plural)");

All FormatterKit.strings have to be adjusted accordingly.

Memory Leaks

Hi there,

there are some memory leaks caused by the fact that mutableCopy returns an owned object. I found two leaks in -[TTTArrayFormatter getObjectValue:forString:errorDescription:] on line 137 and 138, where a mutable copy is created but never released.

A fix would be as easy as calling autorelease just after the mutable copy has been created. I could have fixed it myself however I'd like you to know this memory related convention in Cocoa.

There may be more instances of this problem, these are the ones I stumbled upon.

stringForTimeIntervalFromDate performance issue

I found stringForTimeIntervalFromDate has some perf issue from the instrument data, majorly because it will call [NSCalendar currentCalendar] every time, and it's expensive to do so. My instrument data should 65% time of this call was spend in this line.

stringForTimeIntervalFromDate because one of top 5 expensive functions in my app (because I place it in a table cell so it get executed many times).

- (NSString *)stringForTimeIntervalFromDate:(NSDate *)startingDate
                                     toDate:(NSDate *)endingDate
{
    NSTimeInterval seconds = [startingDate timeIntervalSinceDate:endingDate];
    if (fabs(seconds) < self.presentTimeIntervalMargin) {
        return self.presentDeicticExpression;
    }

    NSCalendar *calendar = [NSCalendar currentCalendar];     <----   65.4%  
    NSUInteger unitFlags = NSYearCalendarUnit | NSMonthCalendarUnit | NSWeekCalendarUnit | NSDayCalendarUnit | NSHourCalendarUnit | NSMinuteCalendarUnit | NSSecondCalendarUnit;
    NSDateComponents *components = [calendar components:unitFlags fromDate:startingDate toDate:endingDate options:0];

Phone formatting support

Any chance of including phone formatting?
For something like this:

@"+1 281-894-9800"
@"+1 (281) 894-9800"

Lossy NSNumber

When NSNumbers are converted to double's or integers, they cannot store as much information as before. For example, in NSNumber "10GB" can be store as number of bytes, but it cannot be stored in a double.

Should we use NSDecimalNumber instead?

Might be related to the way that bytes are converted to bits for calculation too.

"yesterday" not working for .usesIdiomaticDeicticExpressions = YES on iOS 8

localizedIdiomaticDeicticExpressionForComponents doesn't return the expected strings on iOS 8. For some reason [components weekOfYear] returns 2147483647 (max int32) and not 0.

If the following:

else if ([components day] == -1 && [components year] == 0 && [components month] == 0 
         && [components weekOfYear] == 0) {
    return @"yesterday";
}

...is replaced with:

else if ([components day] == -1 && [components year] == 0 && [components month] == 0 
         && ([components weekOfYear] == 0 || [components weekOfYear] == INT32_MAX)) {
    return @"yesterday";
}

It works as expected, but I don't know if that is the way to go. This check might be needed everywhere where you expect . weekOfYear to return a zero.

I would gladly do a PR for this one if this is in fact the best solution :)

Setting Significant Digits on NSNumberFormatter causes problems when changing values

I've run into some issues with the provided NSNumberFormatter when configuring the number of digits.

The configuration I want is at least 1 integer digit, and 1 fraction digit. So 1.5 miles, 10.2 miles, and 300.0 miles for example.

The code in TTTLocationFormatter to create the NSNumberFormatter is as follows:

_numberFormatter = [[NSNumberFormatter alloc] init];
[_numberFormatter setLocale:[NSLocale currentLocale]];
[_numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];
[_numberFormatter setMaximumSignificantDigits:2];
[_numberFormatter setUsesSignificantDigits:YES];

Configuring the formatter in my own code is as follows:

TTTLocationFormatter *formatter = [[TTTLocationFormatter alloc] init];
[formatter setBearingStyle:TTTBearingAbbreviationWordStyle];
formatter.numberFormatter.usesSignificantDigits = NO;
formatter.numberFormatter.minimumIntegerDigits = 1;
formatter.numberFormatter.minimumFractionDigits = 1;
formatter.numberFormatter.maximumFractionDigits = 1;

This does not provide the correct results, even though I'm disabling the uses significant digits property. The output is the same as if I didn't do any configuration, which is 8.2 miles, 10 miles, 100 miles, etc.

If I remove the last two lines in the TTT init so it looks like this:

_numberFormatter = [[NSNumberFormatter alloc] init];
[_numberFormatter setLocale:[NSLocale currentLocale]];
[_numberFormatter setNumberStyle:NSNumberFormatterDecimalStyle];

everything works as expected.

I believe this is actually an Apple bug, but I wanted to bring it up here. Perhaps the TTT default should be different, and not use significant digits as they seem to be broken?

Create "static iOS library" projects

Please add static library projects for those who do not use copy-paste style code sharing.
( like "Drag&Drop sources to your project" and CocoaPods ).

Update podspec to not use localizations

IMHO, the app should be responsible for localizations and not the library.

PaymentKit doesn't include localizations:
https://github.com/stripe/PaymentKit/blob/master/PaymentKit.podspec

Here is the reasoning:
stripe-archive/PaymentKit#33

You could make including localizations a subspec like in Magical record does for "shorthand":
https://github.com/CocoaPods/Specs/blob/master/MagicalRecord/2.2/MagicalRecord.podspec

It seems like a hack to have to run a script to remove some or all localizations as a separate build step.

Apps with FormatterKit are shown to support all languages FormatterKit supports in the App Store

It appears the AppStore detects the localizations provided by FormatterKit and then assumes the app supports all those localizations.

If you take a look at my app the AppStore says it supports ton of languages while I've done nothing to support different languages besides English.

This StackOverflow answer provides more information about how Apple detects languages.

I don't know what FormatterKit can do about this but I thought it useful to create an issue to raise awareness. Duplicate radar 15837695 and hopefully Apple will fix this.

version 1.7.1 breaks functionality in stringForTimeIntervalFromDate:toDate

stringForTimeIntervalFromDate:toDate now gives incorrect days between dates, reverting to version 1.7.0 fixes problem

I was getting values all less than 3 when I would have match dates 15,16 17 days out...code usage which was working fine in 1.7.0:

    [self.timeFormatter setFutureDeicticExpression:nil];
    NSString *formatString = [self.timeFormatter stringForTimeIntervalFromDate:[NSDate date] toDate:matchDate];
    NSTimeInterval seconds = [matchDate timeIntervalSinceDate:[NSDate date]];

TTTTimeIntervalFormatter _approximateQualifierFormat is released twice

In [TTTTimeIntervalFormatter dealloc] the NSString variable _approximateQualifierFormat is released twice.

- (void)dealloc {
    [_locale release];
    [_pastDeicticExpression release];
    [_presentDeicticExpression release];
    [_futureDeicticExpression release];
    [_deicticExpressionFormat release];
    [_approximateQualifierFormat release];
    [_approximateQualifierFormat release];
    [super dealloc];
}

Yesterday not returned correctly for time difference less than 48 hours in TTTTimeIntervalFormatter

let's say now is 14:00
and time in the past is 'Now' minus '(24_60_60 + 14_60_60 + 1)' i.e. 2 days ago at 23:59:59.

stringForTimeIntervalFromDate - returns 'yesterday' incorrectly, this should be 2 days ago

This can be easily fixed in

line 101:
add the following

if ([components day] == -1) {
       NSDateComponents *difference = [self.calendar components:NSSecondCalendarUnit
                                                        fromDate:endingDate toDate:startingDate options:0];

       if ([difference second] > 24*60*60 +
            [[self.calendar components:unitFlags fromDate: startingDate] hour]*60*60 +
            [[self.calendar components:unitFlags fromDate: startingDate] minute]*60 +
            [[self.calendar components:unitFlags fromDate: startingDate] second]) {
            components.day --;
       }
}

What do you think?

Inconsistency

I'm not sure it's that relevant but I wanted to let you know.
When I was making localization test, I've just change the language of the iPad (settings / general / international / language) from English to French but I've left the Region Format as it was (United States).

Then I got some sentences in english, some others in french:

[timeIntervalFormatter stringForTimeInterval:100000]; // dans 1 jour (FRENCH)
[timeIntervalFormatter setUsesIdiomaticDeicticExpressions:YES];
[timeIntervalFormatter stringForTimeInterval:100000]; // tomorrow (ENGLISH)

With a quick investigation I see that: [self.locale objectForKey:NSLocaleLanguageCode]; returns "en" while NSLocalizedStringFromTable returns the french localization

stringForTimeIntervalFromDate return nil

Hi,

I found that sometimes stringForTimeIntervalFromDate return "nil" value, for non-nil input values. It's not always, can't figure out yet why.

here is my configuration

    TTTTimeIntervalFormatter *timeIntervalFormatter = [[TTTTimeIntervalFormatter alloc] init];
    [timeIntervalFormatter setUsesIdiomaticDeicticExpressions:YES];
    [timeIntervalFormatter setPresentTimeIntervalMargin:5];
    [timeIntervalFormatter setLeastSignificantUnit:NSCalendarUnitMinute];

<NSDateComponents: 0x7ffb0d91e560>
Calendar Year: 0
Month: 0
Day: 0
Hour: 0
Minute: 0
Second: -6
Week of Year: 0

TTTTimeIntervalFormatter idiomatic date two days ago sometimes referred to as "yesterday"

Reproduction steps:

TTTTimeIntervalFormatter *formatter = [[TTTTimeIntervalFormatter alloc] init];
formatter.usesIdiomaticDeicticExpressions = YES;
NSDate *date = // 2015-02-22 15:33:50 +0000
NSDate *now = // 2015-02-24 10:13:39 +0000
NSString *human = [formatter stringForTimeIntervalFromDate:now toDate:date];
NSLog(@"Now: %@, Date: %@, Human: %@", now, date, human);

Output:

Now: 2015-02-24 10:13:39 +0000, Date: 2015-02-22 15:33:50 +0000, Human: yesterday

Expected output:

Human: 2 days ago

This line in TTTTimeIntervalFormatter looks only at the "day" component:

} else if ([components day] == -1 && [components year] == 0 && [components month] == 0 && [components weekOfYear] == 0) {
        return @"yesterday";
}

This results in all dates that are more than 24 hours ago, but less than 48 hours ago, being referred to as "yesterday", even when midnight has passed twice.

Make localizedOrdinalIndicatorStringFromNumber public

We're using TTTOrdinalNumberFormatter for localizing ordinal numbers. It's a great library and have saved us a lot of work.

However we need to get the localizedOrdinalIndicatorStringFromNumber separately so we can apply a different font to it.

Is there any reason
- (NSString *)localizedOrdinalIndicatorStringFromNumber:(NSNumber *)number;
Is not a public method?

new tag and update podspec

Do you reckon you could make a 1.0.1 tag and update the podspec? The current version is still the old code from when there was a compiler warning.

Error in Readme

The documentation about TTTTimeIntervalFormatter is showing code sample with wrong results.

[timeIntervalFormatter stringForTimeInterval:0]; // "just now"
[timeIntervalFormatter stringForTimeInterval:100]; // "1 minute ago"
[timeIntervalFormatter stringForTimeInterval:8000]; // "2 hours ago"
[timeIntervalFormatter stringForTimeInterval:100000]; // "yesterday"

Instead of

[timeIntervalFormatter stringForTimeInterval:0]; // "just now"
[timeIntervalFormatter stringForTimeInterval:100]; // "1 minute from now"
[timeIntervalFormatter stringForTimeInterval:8000]; // "2 hours from now"
[timeIntervalFormatter stringForTimeInterval:100000]; // "tomorrow"

Hours, minutes and seconds formatter

Given a NSTimeInterval object, it'd be great if we could interpret it not as an interval since something has happened from the present time (which FormatterKit already does) but rather, just a measure of length of time.

Zombie creation on LocalizeStringForKey

If add localization (Localizable.Strings) to my project and add the German translation, first the view is opened and the localization worked, but if I close that view and open it again its creates a zombie and crash.

TTTTimeIntervalFormatter uses NSLocalizedString instead of NSLocalizedStringFromTable

In order to integrate the FormatterKit, I added the relevant classes and the Localizations to my project. Localization does not work out of the box because the class TTTTimeIntervalFormatter uses method NSLocalizedString, but the localized Strings are in FormatterKit.strings and not in Localizable.strings.

I propose to use NSLocalizedStringFromTable.

Undefined symbol with TTTAddressFormatter

I'm trying to use TTTAddressFormatter with FormatterKit version 1.1.2 integrated via CocoaPods, and I'm getting the following error:

Undefined symbols for architecture i386:
"OBJC_CLASS$_TTTAddressFormatter", referenced from:
objc-class-ref in DBPlacedAcceptedOrderDetailViewController.o
ld: symbol(s) not found for architecture i386
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I tried importing "TTTAddressFormatter.h" and <FormatterKit/TTTAddressFormatter.h> and the result is the same. Note that I have already added imports for AddressBook and AddressBookUI in Prefix.pch. Is there anything else special to do to make it work?

English ordinal for 213 is 'rd'

Because the entire integerValue is tested for intersecting the range 11-13, it misses larger numbers completely: I believe the solution is to test the [number integerValue] % 100 in the enOrdinalIndicatorStringFromNumber: method.

Cocoapods 0.16 install generating incorrect OTHER_LDFLAGS

I know this is a cocoapods issue - but I figured i'd put it here as it was causing me problems and took a while to track down the cause.

When installing formatterKit using the cocoapods 0.16, the OTHER_LDFLAGS arguments are being incorrectly generated.

OTHER_LDFLAGS = -ObjC UI UI UI UI UI UI -framework AddressBook -framework AddressBookUI -framework CoreLocation

The cause seems to be the inclusion of the AddressBook frameworks. I found this same issue referenced in the PhoneGap podspec
https://github.com/CocoaPods/Specs/blob/master/Cordova/2.1.0/Cordova.podspec

My workaround thus far is to comment out the AddressFormatter subspec and the framework inclusion lines in my local podspec.

TTTAddressFormatter & Cocoapods

I get this linking error after installing FormatterKit using cocoapods, and trying to use TTTAddressFormatter in my iOS project:

Undefined symbols for architecture armv7s:
  "_OBJC_CLASS_$_TTTAddressFormatter", referenced from:
      objc-class-ref in [redacted].o
ld: symbol(s) not found for architecture armv7s
clang: error: linker command failed with exit code 1 (use -v to see invocation)

I went through #46 and #94, but can confirm none of the mentionned solutions works in this particular scenario.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.