@@ -18,6 +18,15 @@ public class TimeUnitTests
1818 [ "10m" , new TimeSpan ( 0 , 10 , 0 ) ] ,
1919 [ "10h" , new TimeSpan ( 10 , 0 , 0 ) ] ,
2020 [ "10d" , new TimeSpan ( 10 , 0 , 0 , 0 ) ] ,
21+ [ "1w" , new TimeSpan ( 7 , 0 , 0 , 0 ) ] ,
22+ [ "2w" , new TimeSpan ( 14 , 0 , 0 , 0 ) ] ,
23+ [ "-1w" , new TimeSpan ( - 7 , 0 , 0 , 0 ) ] ,
24+ [ "1M" , new TimeSpan ( ( int ) TimeSpanExtensions . AvgDaysInAMonth , 0 , 0 , 0 ) ] ,
25+ [ "2M" , new TimeSpan ( ( int ) ( 2 * TimeSpanExtensions . AvgDaysInAMonth ) , 0 , 0 , 0 ) ] ,
26+ [ "-1M" , new TimeSpan ( ( int ) ( - 1 * TimeSpanExtensions . AvgDaysInAMonth ) , 0 , 0 , 0 ) ] ,
27+ [ "1y" , new TimeSpan ( ( int ) TimeSpanExtensions . AvgDaysInAYear , 0 , 0 , 0 ) ] ,
28+ [ "2y" , new TimeSpan ( ( int ) ( 2 * TimeSpanExtensions . AvgDaysInAYear ) , 0 , 0 , 0 ) ] ,
29+ [ "-1y" , new TimeSpan ( ( int ) ( - 1 * TimeSpanExtensions . AvgDaysInAYear ) , 0 , 0 , 0 ) ] ,
2130 } ;
2231
2332 [ Theory ]
@@ -50,6 +59,15 @@ public void VerifyParseFailure(string value)
5059 [ InlineData ( "10m" , true ) ]
5160 [ InlineData ( "10h" , true ) ]
5261 [ InlineData ( "10d" , true ) ]
62+ [ InlineData ( "1w" , true ) ]
63+ [ InlineData ( "2w" , true ) ]
64+ [ InlineData ( "-1w" , true ) ]
65+ [ InlineData ( "1M" , true ) ]
66+ [ InlineData ( "2M" , true ) ]
67+ [ InlineData ( "-1M" , true ) ]
68+ [ InlineData ( "1y" , true ) ]
69+ [ InlineData ( "2y" , true ) ]
70+ [ InlineData ( "-1y" , true ) ]
5371 [ InlineData ( null , false ) ]
5472 [ InlineData ( "1.234h" , false ) ] // fractional time
5573 [ InlineData ( "1234" , false ) ] // missing unit
@@ -61,4 +79,49 @@ public void VerifyTryParse(string value, bool expected)
6179 bool success = TimeUnit . TryParse ( value , out var result ) ;
6280 Assert . Equal ( expected , success ) ;
6381 }
82+
83+ [ Fact ]
84+ public void VerifyMonthsVsMinutesCaseSensitive ( )
85+ {
86+ // Uppercase M should be months
87+ var monthResult = TimeUnit . Parse ( "1M" ) ;
88+ var expectedMonthDays = ( int ) TimeSpanExtensions . AvgDaysInAMonth ;
89+ Assert . Equal ( new TimeSpan ( expectedMonthDays , 0 , 0 , 0 ) , monthResult ) ;
90+
91+ // Lowercase m should be minutes
92+ var minuteResult = TimeUnit . Parse ( "1m" ) ;
93+ Assert . Equal ( new TimeSpan ( 0 , 1 , 0 ) , minuteResult ) ;
94+
95+ // Verify they are different
96+ Assert . NotEqual ( monthResult , minuteResult ) ;
97+ }
98+
99+ [ Theory ]
100+ [ InlineData ( "1y" , 365 ) ] // Approximately 365 days in a year
101+ [ InlineData ( "1M" , 30 ) ] // Approximately 30 days in a month
102+ [ InlineData ( "1w" , 7 ) ] // Exactly 7 days in a week
103+ public void VerifyNewTimeUnitsConvertCorrectly ( string input , int expectedApproxDays )
104+ {
105+ var result = TimeUnit . Parse ( input ) ;
106+
107+ // For years and months, check approximate values due to fractional constants
108+ if ( input . EndsWith ( "y" ) )
109+ {
110+ Assert . True ( Math . Abs ( result . TotalDays - TimeSpanExtensions . AvgDaysInAYear ) < 1 ,
111+ $ "Year conversion should be close to { TimeSpanExtensions . AvgDaysInAYear } days, got { result . TotalDays } ") ;
112+ Assert . True ( Math . Abs ( result . TotalDays - expectedApproxDays ) < 10 ,
113+ $ "Year conversion should be approximately { expectedApproxDays } days, got { result . TotalDays } ") ;
114+ }
115+ else if ( input . EndsWith ( "M" ) )
116+ {
117+ Assert . True ( Math . Abs ( result . TotalDays - TimeSpanExtensions . AvgDaysInAMonth ) < 1 ,
118+ $ "Month conversion should be close to { TimeSpanExtensions . AvgDaysInAMonth } days, got { result . TotalDays } ") ;
119+ Assert . True ( Math . Abs ( result . TotalDays - expectedApproxDays ) < 5 ,
120+ $ "Month conversion should be approximately { expectedApproxDays } days, got { result . TotalDays } ") ;
121+ }
122+ else if ( input . EndsWith ( "w" ) )
123+ {
124+ Assert . Equal ( expectedApproxDays , result . TotalDays ) ;
125+ }
126+ }
64127}
0 commit comments