I am trying to extract the number of minutes from user input that is entered in "jira time notation".
For example, I would like to achieve the following results
From research, I have found TimeSpan.ParseExact but I can't figure out how to use this to achieve what I need.
All help would be very much appreciated.
My code so far:
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);
}
I'd probably do something like this and avoid mucking about with Timespan's built-in parsing, given that days per [work] week and [working] hours per [work] day are configurable values in Jira (On our system they are configured as 5 days per week and 8 hours per day, respectively.)
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 ;
}
}
Bit of a sledgehammer approach, but how about:
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;
}
The answer to "what goes here" is, a string built out of the options from Custom Timespan Format Strings. If I'm reading the documentation correctly, characters not in that list -- including whitespace -- have to be escaped with the \
character or surrounded with single quotation marks.
For example, try m\m
to parse "1m", and h\h m\m
to parse "1h 10m". So your code would be:
string[] formats = { "m\m", "h\h\ m\m" };
Caveat: I haven't tried parsing TimeSpan
objects. But I have done DateTime objects, and it is very similar. So I think this should work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With