Refresh interval string localizations
This commit is contained in:
@@ -39,8 +39,10 @@ typedef NS_ENUM(int32_t, TimeUnitType) {
|
||||
|
||||
|
||||
@interface NSDate (Interval)
|
||||
+ (nonnull NSString*)stringForInterval:(Interval)intv rounded:(BOOL)flag;
|
||||
+ (TimeUnitType)unitForInterval:(Interval)intv rounded:(BOOL)flag;
|
||||
+ (nullable NSString*)intStringForInterval:(Interval)intv;
|
||||
+ (nonnull NSString*)floatStringForInterval:(Interval)intv;
|
||||
+ (nullable NSString*)stringForRemainingTime:(NSDate*)other;
|
||||
+ (Interval)floatToIntInterval:(Interval)intv;
|
||||
@end
|
||||
|
||||
|
||||
|
||||
@@ -24,8 +24,6 @@
|
||||
|
||||
#import <QuartzCore/QuartzCore.h>
|
||||
|
||||
static const char _shortnames[] = {'y','w','d','h','m','s'};
|
||||
static const char *_names[] = {"Years", "Weeks", "Days", "Hours", "Minutes", "Seconds"};
|
||||
static const TimeUnitType _values[] = {
|
||||
TimeUnitYears,
|
||||
TimeUnitWeeks,
|
||||
@@ -55,61 +53,58 @@ static const TimeUnitType _values[] = {
|
||||
|
||||
@implementation NSDate (Interval)
|
||||
|
||||
/// If @c flag @c = @c YES, print @c 1.1f float string with single char unit: e.g., 3.3m, 1.7h.
|
||||
+ (nonnull NSString*)stringForInterval:(Interval)intv rounded:(BOOL)flag {
|
||||
if (flag) {
|
||||
unsigned short i = [self floatUnitIndexForInterval:abs(intv)];
|
||||
return [NSString stringWithFormat:@"%1.1f%c", intv / (float)_values[i], _shortnames[i]];
|
||||
/// Short interval formatter string (e.g., '30 min', '2 hrs')
|
||||
+ (nullable NSString*)intStringForInterval:(Interval)intv {
|
||||
TimeUnitType unit = [self unitForInterval:intv];
|
||||
Interval num = intv / unit;
|
||||
NSDateComponents *dc = [[NSDateComponents alloc] init];
|
||||
switch (unit) {
|
||||
case TimeUnitSeconds: dc.second = num; break;
|
||||
case TimeUnitMinutes: dc.minute = num; break;
|
||||
case TimeUnitHours: dc.hour = num; break;
|
||||
case TimeUnitDays: dc.day = num; break;
|
||||
case TimeUnitWeeks: dc.weekOfMonth = num; break;
|
||||
case TimeUnitYears: dc.year = num; break;
|
||||
}
|
||||
unsigned short i = [self exactUnitIndexForInterval:abs(intv)];
|
||||
return [NSString stringWithFormat:@"%d%c", intv / _values[i], _shortnames[i]];
|
||||
return [NSDateComponentsFormatter localizedStringFromDateComponents:dc unitsStyle:NSDateComponentsFormatterUnitsStyleShort];
|
||||
}
|
||||
|
||||
/// @return Highest non-zero unit ( @c flag=YES ). Or highest integer-dividable unit ( @c flag=NO ).
|
||||
+ (TimeUnitType)unitForInterval:(Interval)intv rounded:(BOOL)flag {
|
||||
if (flag) {
|
||||
return _values[[self floatUnitIndexForInterval:abs(intv)]];
|
||||
}
|
||||
return _values[[self exactUnitIndexForInterval:abs(intv)]];
|
||||
/// Print @c 1.1f float string with single char unit: e.g., 3.3m, 1.7h.
|
||||
+ (nonnull NSString*)floatStringForInterval:(Interval)intv {
|
||||
unsigned short i = [self floatUnitIndexForInterval:abs(intv)];
|
||||
return [NSString stringWithFormat:@"%1.1f%c", intv / (float)_values[i], "ywdhms"[i]];
|
||||
}
|
||||
|
||||
/// @return Highest unit type that allows integer division. E.g., '61 minutes'.
|
||||
+ (unsigned short)exactUnitIndexForInterval:(Interval)intv {
|
||||
for (unsigned short i = 0; i < 5; i++)
|
||||
if (intv % _values[i] == 0) return i;
|
||||
return 5; // seconds
|
||||
/// Short interval formatter string for remaining time until @c other date
|
||||
+ (nullable NSString*)stringForRemainingTime:(NSDate*)other {
|
||||
NSDateComponentsFormatter *formatter = [[NSDateComponentsFormatter alloc] init];
|
||||
formatter.unitsStyle = NSDateComponentsFormatterUnitsStyleShort; // e.g., '30 min'
|
||||
formatter.maximumUnitCount = 1;
|
||||
return [formatter stringFromTimeInterval: other.timeIntervalSinceNow];
|
||||
}
|
||||
|
||||
/// Round uneven intervals to highest unit interval. E.g., @c 1:40–>2:00 or @c 1:03–>1:00
|
||||
+ (Interval)floatToIntInterval:(Interval)intv {
|
||||
TimeUnitType unit = _values[[self floatUnitIndexForInterval:abs(intv)]];
|
||||
return (Interval)(roundf((float)intv / unit) * unit);
|
||||
}
|
||||
|
||||
/// @return Highest integer-dividable unit. E.g., '61 minutes'
|
||||
+ (TimeUnitType)unitForInterval:(Interval)intv {
|
||||
if (intv == 0) return TimeUnitMinutes; // fallback to 0 minutes
|
||||
for (unsigned short i = 0; i < 5; i++) // try: years -> minutes
|
||||
if (intv % _values[i] == 0) return _values[i];
|
||||
return TimeUnitSeconds;
|
||||
}
|
||||
|
||||
/// @return Highest non-zero unit type. Can be used with fractions e.g., '1.1 hours'.
|
||||
+ (unsigned short)floatUnitIndexForInterval:(Interval)intv {
|
||||
if (intv == 0) return 4; // fallback to 0 minutes
|
||||
for (unsigned short i = 0; i < 5; i++)
|
||||
if (intv > _values[i]) return i;
|
||||
return 5; // seconds
|
||||
}
|
||||
/* NOT USED
|
||||
/// Convert any unit to the next smaller one. Unit does not have to be exact.
|
||||
+ (TimeUnitType)smallerUnit:(TimeUnitType)unit {
|
||||
if (unit <= TimeUnitHours) return TimeUnitSeconds;
|
||||
if (unit <= TimeUnitDays) return TimeUnitMinutes; // > hours
|
||||
if (unit <= TimeUnitWeeks) return TimeUnitHours; // > days
|
||||
if (unit <= TimeUnitYears) return TimeUnitDays; // > weeks
|
||||
return TimeUnitWeeks; // > years
|
||||
}
|
||||
|
||||
/// @return Formatted string from @c timeIntervalSinceNow.
|
||||
- (nonnull NSString*)intervalStringWithDecimal:(BOOL)flag {
|
||||
return [NSDate stringForInterval:(Interval)[self timeIntervalSinceNow] rounded:flag];
|
||||
}
|
||||
|
||||
/// @return Highest non-zero unit ( @c flag=YES ). Or highest integer-dividable unit ( @c flag=NO ).
|
||||
- (TimeUnitType)unitWithDecimal:(BOOL)flag {
|
||||
Interval absIntv = abs((Interval)[self timeIntervalSinceNow]);
|
||||
if (flag) {
|
||||
return _values[ [NSDate floatUnitIndexForInterval:absIntv] ];
|
||||
}
|
||||
return _values[ [NSDate exactUnitIndexForInterval:absIntv] ];
|
||||
}
|
||||
*/
|
||||
@end
|
||||
|
||||
|
||||
@@ -122,7 +117,7 @@ static const TimeUnitType _values[] = {
|
||||
|
||||
/// Configure both @c NSControl elements based on the provided interval @c intv.
|
||||
+ (void)setInterval:(Interval)intv forPopup:(NSPopUpButton*)popup andField:(NSTextField*)field animate:(BOOL)flag {
|
||||
TimeUnitType unit = [self unitForInterval:intv rounded:NO];
|
||||
TimeUnitType unit = [self unitForInterval:intv];
|
||||
int num = (int)(intv / unit);
|
||||
if (flag && popup.selectedTag != unit) [self animateControlSize:popup];
|
||||
if (flag && field.intValue != num) [self animateControlSize:field];
|
||||
@@ -133,11 +128,12 @@ static const TimeUnitType _values[] = {
|
||||
/// Insert all @c TimeUnitType items into popup button. Save unit value into @c tag attribute.
|
||||
+ (void)populateUnitsMenu:(NSPopUpButton*)popup selected:(TimeUnitType)unit {
|
||||
[popup removeAllItems];
|
||||
for (NSUInteger i = 0; i < 6; i++) {
|
||||
[popup addItemWithTitle:[NSString stringWithUTF8String:_names[i]]];
|
||||
NSMenuItem *item = popup.lastItem;
|
||||
[item setKeyEquivalent:[[NSString stringWithFormat:@"%c", _shortnames[i]] uppercaseString]];
|
||||
item.tag = _values[i];
|
||||
[popup addItemsWithTitles:@[NSLocalizedString(@"Years", nil), NSLocalizedString(@"Weeks", nil),
|
||||
NSLocalizedString(@"Days", nil), NSLocalizedString(@"Hours", nil),
|
||||
NSLocalizedString(@"Minutes", nil), NSLocalizedString(@"Seconds", nil)]];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
[popup itemAtIndex:i].tag = _values[i];
|
||||
[popup itemAtIndex:i].keyEquivalent = [NSString stringWithFormat:@"%d", i+1]; // Cmd+1 .. Cmd+6
|
||||
}
|
||||
[popup selectItemWithTag:unit];
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user