2013-08-28 12 views
11

Quindi la mia intenzione è quella di mettere le date che sarebbe simile alla seguente out:NSDateFormatter relativa data di formattazione con formato personalizzato

Today, August 28 
Tomorrow, August 29 
Friday, August 30 
...etc 

Il problema è che sembra posso solo arrivare così vicino.

Quando ho setDoesRelativeDateFormatting:YES e setDateStyle-Full e setTimeStyle-None, produce risultati come questo:

Today 
Tomorrow 
Friday, August 30, 2013 

Questo produce l'anno e non cede mese e la data per oggi e domani.

L'altro codice che ho provato è questo:

[NSDateFormatter dateFormatFromTemplate:@"eeeedMMM" options:0 
                locale:[NSLocale currentLocale]]; 

e che produce il seguente:

Wednesday, August 28 
Thursday, August 29 
Friday, August 30 

Apparentemente, il dateStyle e timeStyle, oppure la data di formattazione relativa ignora il formato personalizzato .

C'è un modo per realizzare questo formato di data senza entrare in un'implementazione personalizzata?

Grazie in anticipo!

risposta

3

Sulla base della documentazione relativa a NSDateFormatter, ritengo che l'unica soluzione per il problema sia presentare due stringhe di data per i giorni in cui si desidera essere mostrati relativamente. Tieni presente che in diverse lingue ci sono differenze nelle date relative. Dalla documentazione:

Se una data formattatore utilizza la formattazione data relativa, ove possibile sostituisce la componente data della sua uscita con una frase, ad esempio “oggi” o “domani”, cioè indica una data relativa. Le frasi disponibili dipendono dalle impostazioni internazionali per il formattatore della data; considerando che, per le date in futuro, l'inglese può consentire solo “domani” francese può permettere “il giorno dopo il giorno dopo domani".

Credo che se si definisce che si sta andando a mostrare relativamente a esempio ieri, oggi e domani è possibile utilizzare 2 NSDateFormatters: con il primo si visualizzerà il valore relativo e con il secondo si visualizzerà la data effettiva Per le date non relative verrà visualizzato solo il valore non relativo

+0

rmaddy non ha chiesto la questione. – vikingosegundo

+1

Il trucco è scoprire quando la relativa formattazione è effettivamente avvenuta. Non puoi fare affidamento solo su un giorno prima e uno dopo. In altre lingue, ad esempio francese e russo, avrai una formattazione relativa per "prima di ieri" e "dopo domani". – Davyd

+0

Soluzione brillante! –

2

Sembra che non ci sia modo di realizzare questo tipo di formattazione della data senza andare in un'implementazione personalizzata. Quindi, la risposta breve a questa domanda è 'No'.

Tuttavia, il problema esiste ancora, quindi di seguito è la mia soluzione al problema.

Creare una sottoclasse di NSDateFormatter e implementare il metodo personalizzato init e override stringFromDate:.

- (instancetype)initWithDateFormat:(NSString *)dateFormat 
{ 
    self = [super init]; 
    if (self) { 
     NSLocale *locale = [NSLocale currentLocale]; 
     self.locale = locale; 

     self.timeStyle = NSDateFormatterNoStyle; 
     self.dateStyle = NSDateFormatterShortStyle; 
     self.doesRelativeDateFormatting = YES; 

     self.dateFormat = dateFormat; 
    } 
    return self; 
} 

- (NSString *)stringFromDate:(NSDate *)date 
{ 
    NSString *dateFormat = self.dateFormat; 
    self.dateFormat = nil; 

    BOOL didRelativeDateFormatting = self.doesRelativeDateFormatting; 
    self.doesRelativeDateFormatting = YES; 

    NSString *result = [super stringFromDate:date]; 

    if ([result rangeOfCharacterFromSet:[NSCharacterSet decimalDigitCharacterSet]].location != NSNotFound) { 
     self.dateFormat = dateFormat; 
     self.doesRelativeDateFormatting = NO; 
     result = [super stringFromDate:date]; 
    } 

    self.dateFormat = dateFormat; 
    self.doesRelativeDateFormatting = didRelativeDateFormatting; 

    return result; 
} 

Da doesRelativeDateFormatting e dateFormat sono mutuamente esclusivi cerchiamo di utilizzare la formattazione relativa prima. Dato che abbiamo impostato self.dateStyle = NSDateFormatterShortStyle nel metodo init, sappiamo che la data conterrà i numeri decimali a meno che non venga sostituita con parole che significano "oggi", "domani" e qualsiasi cosa che possa apparire in altre lingue. Se non abbiamo individuato alcun numero accettiamo questo risultato.

Se nella stringa ci sono numeri digitali, si presume che la relativa formattazione non sia avvenuta, quindi applichiamo il nostro formato di data.

3

Io uso questo approccio a Swift 3:

struct SharedFormatters { 
    private static let dateWithRelativeFormatting: DateFormatter = { 
     let df = DateFormatter() 
     df.dateStyle = .medium 
     df.doesRelativeDateFormatting = true 
     return df 
    }() 
    private static let dateWithoutRelativeFormatting: DateFormatter = { 
     let df = DateFormatter() 
     df.dateStyle = .medium 
     df.doesRelativeDateFormatting = false 
     return df 
    }() 
    private static let longDateWithoutYear: DateFormatter = { 
     let df = DateFormatter() 
     df.dateFormat = "MMMM d" 
     df.doesRelativeDateFormatting = false 
     return df 
    }() 
    static func string(from date: Date) -> String { 
     let val = dateWithRelativeFormatting.string(from: date) 
     let val2 = dateWithoutRelativeFormatting.string(from: date) 
     return val == val2 ? longDateWithoutYear.string(from: date) : val 
    } 
} 
+1

Questa è davvero una buona idea. Fai attenzione se hai molte date da formattare (ad esempio in una tabella) poiché questo triplica il numero di formattazioni in corso. –