Skip to content

Commit 1cc1ea0

Browse files
committed
#33 - DateSerial parser.
1 parent e370426 commit 1cc1ea0

File tree

4 files changed

+166
-0
lines changed

4 files changed

+166
-0
lines changed
Lines changed: 84 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,84 @@
1+
using ReportViewer.NET.DataObjects;
2+
using ReportViewer.NET.Extensions;
3+
using System.Collections.Generic;
4+
using System.Text.RegularExpressions;
5+
using System;
6+
7+
namespace ReportViewer.NET.Parsers.DateAndTime
8+
{
9+
public class DateSerialParser : BaseParser
10+
{
11+
public static Regex DateSerialRegex = RegexCommon.GenerateMultiParamParserRegex("DateSerial");
12+
13+
public DateSerialParser(
14+
string currentString,
15+
ExpressionFieldOperator op,
16+
ReportExpression currentExpression,
17+
IEnumerable<IDictionary<string, object>> dataSetResults,
18+
IDictionary<string, object> values,
19+
int currentRowNumber,
20+
IEnumerable<DataSet> dataSets,
21+
DataSet activeDataset,
22+
ReportRDL report
23+
) : base(currentString, op, currentExpression, dataSetResults, values, currentRowNumber, dataSets, activeDataset, DateSerialRegex, report)
24+
{
25+
}
26+
27+
public override (Type, object) ExtractExpressionValue(string fieldName, string dataSetName)
28+
{
29+
throw new NotImplementedException();
30+
}
31+
32+
public override void Parse()
33+
{
34+
var match = DateSerialRegex.Match(CurrentString);
35+
var matchValue = match.Value;
36+
37+
// Remove the surrounding DateSerial including open & close brace so we can inspect inner members and see if they too contain program flow expressions.
38+
matchValue = matchValue.MatchValueSubString(11);
39+
40+
var foundParameters = this.ParseParenthesis(matchValue);
41+
42+
if (foundParameters.Item2.Count != 3)
43+
{
44+
// The DateSerial function expects 3 parameters.
45+
return;
46+
}
47+
48+
// DateTime will either come directly from database or will be calculated from other expression.
49+
var year = this.Report.Parser.ParseReportExpressionString(
50+
foundParameters.Item2[0],
51+
this.DataSetResults,
52+
this.Values,
53+
this.CurrentRowNumber,
54+
this.DataSets,
55+
this.ActiveDataset,
56+
null
57+
).ExpressionAsInt();
58+
59+
var month = this.Report.Parser.ParseReportExpressionString(
60+
foundParameters.Item2[1],
61+
this.DataSetResults,
62+
this.Values,
63+
this.CurrentRowNumber,
64+
this.DataSets,
65+
this.ActiveDataset,
66+
null
67+
).ExpressionAsInt();
68+
69+
var day = this.Report.Parser.ParseReportExpressionString(
70+
foundParameters.Item2[2],
71+
this.DataSetResults,
72+
this.Values,
73+
this.CurrentRowNumber,
74+
this.DataSets,
75+
this.ActiveDataset,
76+
null
77+
).ExpressionAsInt();
78+
79+
this.CurrentExpression.Index = match.Index;
80+
this.CurrentExpression.ResolvedType = typeof(DateTime);
81+
this.CurrentExpression.Value = new DateTime(year, month, day, 0, 0, 0);
82+
}
83+
}
84+
}

src/ReportViewer.NET/Parsers/ExpressionFieldOperator.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@ public enum ExpressionFieldOperator
5656
DateAdd,
5757
DateDiff,
5858
DatePart,
59+
DateSerial,
5960
Day,
6061
Now,
6162
DateValue,

src/ReportViewer.NET/Parsers/ExpressionParser.cs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,15 @@ ref string proposedString
515515
proposedString = datePartParser.GetProposedString();
516516
}
517517

518+
if (DateSerialParser.DateSerialRegex.IsMatch(currentString) &&
519+
(currentExpression.Operator == ExpressionFieldOperator.None || DateSerialParser.DateSerialRegex.Match(currentString).Index < currentExpression.Index)
520+
)
521+
{
522+
var dateSerialParser = new DateSerialParser(currentString, ExpressionFieldOperator.DateSerial, currentExpression, dataSetResults, values, currentRowNumber, dataSets, activeDataset, _report);
523+
dateSerialParser.Parse();
524+
proposedString = dateSerialParser.GetProposedString();
525+
}
526+
518527
if (DayParser.DayRegex.IsMatch(currentString) &&
519528
((WeekdayParser.WeekdayRegex.IsMatch(currentString) && DayParser.DayRegex.Match(currentString).Index < WeekdayParser.WeekdayRegex.Match(currentString).Index) || !WeekdayParser.WeekdayRegex.IsMatch(currentString)) &&
520529
(currentExpression.Operator == ExpressionFieldOperator.None || DayParser.DayRegex.Match(currentString).Index < currentExpression.Index)
Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
using Microsoft.VisualStudio.TestTools.UnitTesting;
2+
using ReportViewer.NET.DataObjects;
3+
using ReportViewer.NET.Extensions;
4+
using ReportViewer.NET.Parsers;
5+
using System.Globalization;
6+
7+
namespace ReportViewer.NET.Tests.Parsers.DateAndTime
8+
{
9+
[TestClass]
10+
public class DateSerialParserTests
11+
{
12+
private ExpressionParser _expressionParser;
13+
private ReportRDL _report;
14+
15+
public DateSerialParserTests()
16+
{
17+
var report = TestHelper.PrimeReport();
18+
19+
_report = report;
20+
_expressionParser = new ExpressionParser(report);
21+
}
22+
23+
[TestMethod]
24+
public void DateSerial_Returns_DateTime()
25+
{
26+
// Arrange
27+
var expr = "=DateSerial(DatePart(\"yyyy\",\"January 15, 2010 14:30:15\")-10, DatePart(\"m\",\"January 15, 2010 14:30:15\")+3,DatePart(\"d\",\"January 15, 2010 14:30:15\")-1)";
28+
29+
// Act
30+
var result = _expressionParser.ParseReportExpressionString(
31+
expr,
32+
null,
33+
null,
34+
1,
35+
_report.DataSets,
36+
null,
37+
null
38+
).ExpressionAsDateTime();
39+
40+
// Assert
41+
Assert.AreEqual(new DateTime(2000, 4, 14, 0, 0, 0), result);
42+
}
43+
44+
[TestMethod]
45+
public void DateSerial_Returns_String()
46+
{
47+
// Arrange
48+
var expr = "=\"DateSerial parsed as \" & FormatDateTime(DateSerial(DatePart(\"yyyy\",\"January 15, 2010 14:30:15\")-10, DatePart(\"m\",\"January 15, 2010 14:30:15\")+3,DatePart(\"d\",\"January 15, 2010 14:30:15\")-1), DateFormat.ShortDate)";
49+
var cultureInfo = new CultureInfo("en-GB");
50+
CultureInfo originalCulture = Thread.CurrentThread.CurrentCulture;
51+
CultureInfo.DefaultThreadCurrentCulture = cultureInfo;
52+
CultureInfo.DefaultThreadCurrentUICulture = cultureInfo;
53+
54+
// Act
55+
var result = _expressionParser.ParseReportExpressionString(
56+
expr,
57+
null,
58+
null,
59+
1,
60+
_report.DataSets,
61+
null,
62+
null
63+
).ExpressionAsString();
64+
65+
// Assert
66+
Assert.AreEqual("DateSerial parsed as 14/04/2000", result);
67+
68+
CultureInfo.DefaultThreadCurrentCulture = originalCulture;
69+
CultureInfo.DefaultThreadCurrentUICulture = originalCulture;
70+
}
71+
}
72+
}

0 commit comments

Comments
 (0)