2013-10-22 13 views
5

Sto cercando di estrarre il numero di minuti dall'input dell'utente immesso in "notazione ora jira".Estratto minuti dalla stringa del tempo in "notazione jira"

Per esempio, vorrei raggiungere i seguenti risultati

  • ingresso: "30m"/uscita: 30
  • ingresso: "1h 20m"/uscita: 80
  • ingresso: "3h "/ Output 180

Dalla ricerca, ho trovato TimeSpan.ParseExact ma non riesco a capire come usarlo per ottenere ciò di cui ho bisogno.

Tutto l'aiuto sarebbe molto apprezzato.

Il mio codice finora:

public static int TextToMins(string TimeText) 
    { 
     CultureInfo culture = new CultureInfo("en-IE"); 
     string[] formats = { "What goes here?" }; 
     TimeSpan ts = TimeSpan.ParseExact(TimeText.Trim().ToLower(), formats, culture); 
     return Convert.ToInt32(ts.TotalMinutes); 
    } 
+0

Ho modificato il titolo. Per favore vedi, "[Le domande dovrebbero includere" tag "nei loro titoli?] (Http://meta.stackexchange.com/questions/19190/)", dove il consenso è "no, non dovrebbero". –

risposta

1

po 'di un approccio mazza, ma che ne dici:

public static int TextToMins(string timeText) 
{ 
    var total = 0; 
    foreach (var part in timeText.Split(' ')) 
    { 
     if (part[part.Length - 1] == 'h') 
     { 
      total += 60 * int.Parse(part.Trim('h')); 
     } 
     else 
     { 
      total += int.Parse(part.Trim('m')); 
     } 
    } 
    return total; 
} 
+0

Funziona per me! Grazie! – user1515364

+0

@ user1515364 Felice di sentirlo. Però non è una soluzione così chiara al problema. Ma se fa il lavoro, ed è leggibile, probabilmente è abbastanza buono ... –

1

La risposta alla domanda "che cosa va qui" è una stringa costruito fuori delle opzioni da Custom Timespan Format Strings. Se sto leggendo la documentazione correttamente, i caratteri non inclusi in quell'elenco, inclusi gli spazi bianchi, devono essere salvati con il carattere \ o racchiusi tra virgolette singole.

Ad esempio, provare m\m per analizzare "1m" e h\h m\m per analizzare "1h 10m". Quindi il tuo codice sarebbe:

string[] formats = { "m\m", "h\h\ m\m" }; 

Avvertenza: non ho provato ad analizzare gli oggetti TimeSpan. Ma ho fatto oggetti DateTime, ed è molto simile. Quindi penso che dovrebbe funzionare.

3

Probabilmente farei qualcosa del genere ed evitare di fare il pasticcio con l'analisi incorporata di Timespan, dato che i giorni per [lavoro] settimana e [lavoro] ore per [lavoro] giorno sono valori configurabili in Jira (Sul nostro sistema sono configurati come 5 giorni a settimana e 8 ore al giorno, rispettivamente.)

class JiraTimeDurationParser 
{ 

    /// <summary> 
    /// Jira's configured value for [working] days per week ; 
    /// </summary> 
    public ushort DaysPerWeek  { get ; private set ; } 

    /// <summary> 
    /// Jira's configured value for [working] hours per day 
    /// </summary> 
    public ushort HoursPerDay  { get ; private set ; } 

    public JiraTimeDurationParser(ushort daysPerWeek = 5 , ushort hoursPerDay = 8) 
    { 
    if (daysPerWeek < 1 || daysPerWeek > 7) throw new ArgumentOutOfRangeException("daysPerWeek" ) ; 
    if (hoursPerDay < 1 || hoursPerDay > 24) throw new ArgumentOutOfRangeException("hoursPerDay" ) ; 

    this.DaysPerWeek = daysPerWeek ; 
    this.HoursPerDay = hoursPerDay ; 

    return ; 
    } 

    private static Regex rxDuration = new Regex(@" 
    ^         # drop anchor at start-of-line 
     [\x20\t]* ((?<weeks> \d+) w)? # Optional whitespace, followed by an optional number of weeks 
     [\x20\t]* ((?<days> \d+) d)? # Optional whitesapce, followed by an optional number of days 
     [\x20\t]* ((?<hours> \d+) h)? # Optional whitespace, followed by an optional number of hours 
     [\x20\t]* ((?<minutes> \d+) m) # Optional whitespace, followed by a mandatory number of minutes 
     [\x20\t]*       # Optional trailing whitespace 
    $         # followed by end-of-line 
    " , 
    RegexOptions.IgnorePatternWhitespace 
    ) ; 

    public TimeSpan Parse(string jiraDuration) 
    { 
    if (string.IsNullOrEmpty(jiraDuration)) throw new ArgumentOutOfRangeException("jiraDuration"); 

    Match m = rxDuration.Match(jiraDuration) ; 
    if (!m.Success) throw new ArgumentOutOfRangeException("jiraDuration") ; 

    int weeks ; bool hasWeeks = int.TryParse(m.Groups[ "weeks" ].Value , out weeks ) ; 
    int days ; bool hasDays = int.TryParse(m.Groups[ "days" ].Value , out days ) ; 
    int hours ; bool hasHours = int.TryParse(m.Groups[ "hours" ].Value , out hours ) ; 
    int minutes ; bool hasMinutes = int.TryParse(m.Groups[ "minutes" ].Value , out minutes) ; 

    bool isValid = hasWeeks|hasDays|hasHours|hasMinutes ; 
    if (!isValid) throw new ArgumentOutOfRangeException("jiraDuration") ; 

    TimeSpan duration = new TimeSpan(weeks*DaysPerWeek*HoursPerDay + days*HoursPerDay + hours , minutes , 0); 
    return duration ; 

    } 

    public bool TryParse(string jiraDuration , out TimeSpan timeSpan) 
    { 
    bool success ; 
    try 
    { 
     timeSpan = Parse(jiraDuration) ; 
     success = true ; 
    } 
    catch 
    { 
     timeSpan = default(TimeSpan) ; 
     success = false ; 
    } 
    return success ; 
    } 

} 
+0

Un paio di piccoli errori nel codice; fisso. –

1

Appena avuto lo stesso problema. Ecco la mia soluzione (unità di test), per quel che vale:

public static TimeSpan Parse(string s) 
{ 
    long seconds = 0; 
    long current = 0; 

    int len = s.Length; 
    for (int i=0; i<len; ++i) 
    { 
     char c = s[i]; 

     if (char.IsDigit(c)) 
     { 
      current = current * 10 + (int)char.GetNumericValue(c); 
     } 
     else if (char.IsWhiteSpace(c)) 
     { 
      continue; 
     } 
     else 
     { 
      long multiplier; 

      switch (c) 
      { 
       case 's': multiplier = 1; break;  // seconds 
       case 'm': multiplier = 60; break;  // minutes 
       case 'h': multiplier = 3600; break; // hours 
       case 'd': multiplier = 86400; break; // days 
       case 'w': multiplier = 604800; break; // weeks 
       default: 
        throw new FormatException(
         String.Format(
          "'{0}': Invalid duration character {1} at position {2}. Supported characters are s,m,h,d, and w", s, c, i)); 
      } 

      seconds += current * multiplier; 
      current = 0; 
     } 
    } 

    if (current != 0) 
    { 
     throw new FormatException(
      String.Format("'{0}': missing duration specifier in the end of the string. Supported characters are s,m,h,d, and w", s)); 
    } 

    return TimeSpan.FromSeconds(seconds); 
} 
2

Il seguente codice analizzare le stringhe come: "1h", "1h30m", "12h 45m", "1 h 4 m", "1D 12h 34m 20s "," 80h "," 3000ms "," 20mins "," 1min ".

In ogni caso "gli spazi vengono ignorati", supportano "giorni, ore, minuti, secondi e millisecondi" ma facilmente è possibile aggiungere mesi, settimane, anni, ecc. Basta aggiungere l'espressione corretta nell'elenco delle condizioni .

public static TimeSpan ParseHuman(string dateTime) 
{ 
    TimeSpan ts = TimeSpan.Zero; 
    string currentString = ""; string currentNumber = ""; 
    foreach (char ch in dateTime+' ') 
     { 
      currentString += ch; 
      if (Regex.IsMatch(currentString, @"^(days(\d|\s)|day(\d|\s)|d(\d|\s))", RegexOptions.IgnoreCase)) { ts = ts.Add(TimeSpan.FromDays(int.Parse(currentNumber))); currentString = ""; currentNumber = ""; } 
      if (Regex.IsMatch(currentString, @"^(hours(\d|\s)|hour(\d|\s)|h(\d|\s))", RegexOptions.IgnoreCase)) { ts = ts.Add(TimeSpan.FromHours(int.Parse(currentNumber))); currentString = ""; currentNumber = ""; } 
      if (Regex.IsMatch(currentString, @"^(ms(\d|\s))", RegexOptions.IgnoreCase)) { ts = ts.Add(TimeSpan.FromMilliseconds(int.Parse(currentNumber))); currentString = ""; currentNumber = ""; } 
      if (Regex.IsMatch(currentString, @"^(mins(\d|\s)|min(\d|\s)|m(\d|\s))", RegexOptions.IgnoreCase)) { ts = ts.Add(TimeSpan.FromMinutes(int.Parse(currentNumber))); currentString = ""; currentNumber = ""; } 
      if (Regex.IsMatch(currentString, @"^(secs(\d|\s)|sec(\d|\s)|s(\d|\s))", RegexOptions.IgnoreCase)) { ts = ts.Add(TimeSpan.FromSeconds(int.Parse(currentNumber))); currentString = ""; currentNumber = ""; } 
      if (Regex.IsMatch(ch.ToString(), @"\d")) { currentNumber += ch; currentString = ""; } 
     } 
    return ts; 
} 
+0

Mi è piaciuta l'idea.Ma fallisce per string ** 3days 20hours 36mins 17secs 156ms ** – Milad

+1

@Milad, hai ragione, l'ho risolto, ora copre tutti i casi. –