@@ -18,6 +18,15 @@ public class TimeUnitTests
18
18
[ "10m" , new TimeSpan ( 0 , 10 , 0 ) ] ,
19
19
[ "10h" , new TimeSpan ( 10 , 0 , 0 ) ] ,
20
20
[ "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 ) ] ,
21
30
} ;
22
31
23
32
[ Theory ]
@@ -50,6 +59,15 @@ public void VerifyParseFailure(string value)
50
59
[ InlineData ( "10m" , true ) ]
51
60
[ InlineData ( "10h" , true ) ]
52
61
[ 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 ) ]
53
71
[ InlineData ( null , false ) ]
54
72
[ InlineData ( "1.234h" , false ) ] // fractional time
55
73
[ InlineData ( "1234" , false ) ] // missing unit
@@ -61,4 +79,49 @@ public void VerifyTryParse(string value, bool expected)
61
79
bool success = TimeUnit . TryParse ( value , out var result ) ;
62
80
Assert . Equal ( expected , success ) ;
63
81
}
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
+ }
64
127
}
0 commit comments