Skip to content

Commit

Permalink
Adding DateTime and Timespan support (#17)
Browse files Browse the repository at this point in the history
added datetime/timespan support for + and - operators, fleshed out date time add, subtract, and negate operations and added unit tests
  • Loading branch information
some1one authored and VitaliyMF committed Mar 29, 2019
1 parent 78a9512 commit 87fed74
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 4 deletions.
18 changes: 18 additions & 0 deletions src/NReco.LambdaParser.Tests/LambdaParserTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@ public class LambdaParserTests {
varContext["nullVar"] = null;
varContext["name_with_underscore"] = "a_b";
varContext["_name_with_underscore"] = "_a_b";
varContext["day1"] = new DateTime().AddDays(1);
varContext["day2"] = new DateTime().AddDays(2);
varContext["oneDay"] = new TimeSpan(1,0,0,0);
varContext["twoDays"] = new TimeSpan(2,0,0,0);
return varContext;
}

Expand Down Expand Up @@ -102,6 +106,20 @@ public class LambdaParserTests {

Assert.True((bool)lambdaParser.Eval("5>two && (5>7 || test.Contains(\"t\") )", varContext));
Assert.True((bool)lambdaParser.Eval("null!=test && test!=null && test.Contains(\"t\") && true == Yes && false==!Yes && false!=Yes", varContext));

Assert.Equal(new DateTime().AddDays(2), lambdaParser.Eval("day1 + oneDay", varContext));
Assert.Equal(new DateTime().AddDays(2), lambdaParser.Eval("oneDay + day1", varContext));
Assert.Equal(new DateTime().AddDays(1), lambdaParser.Eval("day2 - oneDay", varContext));
Assert.Equal(new DateTime().AddDays(1), lambdaParser.Eval("day2 + -oneDay", varContext));
Assert.Equal(new DateTime().AddDays(1), lambdaParser.Eval("-oneDay + day2", varContext));
Assert.Equal(new TimeSpan(1,0,0,0), lambdaParser.Eval("day2 - day1", varContext));
Assert.Equal(new TimeSpan(1,0,0,0).Negate(), lambdaParser.Eval("day1 - day2", varContext));
Assert.Equal(new TimeSpan(1,0,0,0), lambdaParser.Eval("day2 - day1", varContext));
Assert.Equal(new TimeSpan(2,0,0,0), lambdaParser.Eval("oneDay + oneDay", varContext));
Assert.Equal(new TimeSpan(1,0,0,0), lambdaParser.Eval("twoDays - oneDay", varContext));
Assert.Equal(new TimeSpan(1,0,0,0), lambdaParser.Eval("twoDays + -oneDay", varContext));
Assert.Equal(new TimeSpan(1,0,0,0).Negate(), lambdaParser.Eval("oneDay - twoDays", varContext));
Assert.Equal(new TimeSpan(1,0,0,0).Negate(), lambdaParser.Eval("-twoDays + oneDay", varContext));
}

[Fact]
Expand Down
8 changes: 8 additions & 0 deletions src/NReco.LambdaParser.Tests/ValueComparerTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,14 @@ public class ValueComparerTests {
Assert.Equal(cmp.Compare(5, null), 1);
Assert.Equal(cmp.Compare(null, 0), -1);
Assert.Equal(cmp.Compare(null, null), 0); // two nulls are equal like in C#

Assert.Equal(cmp.Compare(new DateTime(), new DateTime().AddDays(1)), -1);
Assert.Equal(cmp.Compare(new DateTime().AddDays(1), new DateTime()), 1);
Assert.Equal(cmp.Compare(new DateTime(), new DateTime()), 0);

Assert.Equal(cmp.Compare(new TimeSpan(), new TimeSpan()), 0);
Assert.Equal(cmp.Compare(new TimeSpan(), new TimeSpan(0,0,1)), -1);
Assert.Equal(cmp.Compare(new TimeSpan(0,0,1), new TimeSpan()), 1);
}

[Fact]
Expand Down
43 changes: 39 additions & 4 deletions src/NReco.LambdaParser/Linq/LambdaParameterWrapper.cs
Original file line number Diff line number Diff line change
Expand Up @@ -186,20 +186,55 @@ internal sealed class LambdaParameterWrapper : IComparable {
public static LambdaParameterWrapper operator +(LambdaParameterWrapper c1, LambdaParameterWrapper c2) {
if (c1.Value is string || c2.Value is string) {
return new LambdaParameterWrapper( Convert.ToString(c1.Value) + Convert.ToString(c2.Value), c1.Cmp);
} else {
var c1decimal = Convert.ToDecimal(c1.Value, CultureInfo.InvariantCulture);
var c2decimal = Convert.ToDecimal(c2.Value, CultureInfo.InvariantCulture);
return new LambdaParameterWrapper(c1decimal + c2decimal, c1.Cmp);
}

if (c1.Value is TimeSpan c1TimeSpan && c2.Value is DateTime c2DateTime)
{
return new LambdaParameterWrapper(c2DateTime.Add(c1TimeSpan), c1.Cmp);
}

if (c1.Value is DateTime c1DateTime && c2.Value is TimeSpan c2TimeSpan)
{
return new LambdaParameterWrapper(c1DateTime.Add(c2TimeSpan), c1.Cmp);
}

if (c1.Value is TimeSpan c1ts && c2.Value is TimeSpan c2ts)
{
return new LambdaParameterWrapper(c1ts + c2ts, c1.Cmp);
}

var c1decimal = Convert.ToDecimal(c1.Value, CultureInfo.InvariantCulture);
var c2decimal = Convert.ToDecimal(c2.Value, CultureInfo.InvariantCulture);
return new LambdaParameterWrapper(c1decimal + c2decimal, c1.Cmp);
}

public static LambdaParameterWrapper operator -(LambdaParameterWrapper c1, LambdaParameterWrapper c2) {
if (c1.Value is TimeSpan c1ts && c2.Value is TimeSpan c2ts)
{
return new LambdaParameterWrapper(c1ts - c2ts, c1.Cmp);
}

if (c1.Value is DateTime c1dt && c2.Value is DateTime c2dt)
{
return new LambdaParameterWrapper(c1dt - c2dt, c1.Cmp);
}

if (c1.Value is DateTime c1DateTime && c2.Value is TimeSpan c2TimeSpan)
{
return new LambdaParameterWrapper(c1DateTime.Add(c2TimeSpan.Negate()), c1.Cmp);
}

var c1decimal = Convert.ToDecimal(c1.Value, CultureInfo.InvariantCulture);
var c2decimal = Convert.ToDecimal(c2.Value, CultureInfo.InvariantCulture);
return new LambdaParameterWrapper(c1decimal - c2decimal, c1.Cmp);
}

public static LambdaParameterWrapper operator -(LambdaParameterWrapper c1) {
if(c1.Value is TimeSpan ts)
{
return new LambdaParameterWrapper(ts.Negate(), c1.Cmp);
}

var c1decimal = Convert.ToDecimal(c1.Value, CultureInfo.InvariantCulture);
return new LambdaParameterWrapper(-c1decimal, c1.Cmp);
}
Expand Down

0 comments on commit 87fed74

Please sign in to comment.