diff --git a/server/AyaNova/DataList/DataListSqlFilterCriteriaBuilder.cs b/server/AyaNova/DataList/DataListSqlFilterCriteriaBuilder.cs index a62ff718..041e2ec7 100644 --- a/server/AyaNova/DataList/DataListSqlFilterCriteriaBuilder.cs +++ b/server/AyaNova/DataList/DataListSqlFilterCriteriaBuilder.cs @@ -141,7 +141,7 @@ namespace AyaNova.DataList DataTypeToFilter = (UiFieldDataType)dataType; columnNameToFilter = DataListField.GetSqlValueColumnName(); //Append this filter's criteria - sb.Append(DataFilterToColumnCriteria(columnNameToFilter, DataTypeToFilter, filterItem.op, filterItem.value)); + sb.Append(DataFilterToColumnCriteria(columnNameToFilter, DataTypeToFilter, filterItem.op, filterItem.value, listOptions.ClientTimeStamp)); ThisIsTheFirstFilterItemForThisColumn = false; @@ -182,7 +182,7 @@ namespace AyaNova.DataList /// /// Translate DataFilter to Postgres friendly SQL criteria /// - private static string DataFilterToColumnCriteria(string SqlColumnNameToFilter, UiFieldDataType DataType, string sOperator, string sValue) + private static string DataFilterToColumnCriteria(string SqlColumnNameToFilter, UiFieldDataType DataType, string sOperator, string sValue, DateTimeOffset clientTimeStamp) { // bool TagFilter = sTags.Count < 0; Nope, the datatype already states if it's tags or not no need for redundancy @@ -426,120 +426,19 @@ namespace AyaNova.DataList //listOptions.ClientTimeStamp.DateTime contains the exact client time and date as expected //################################################################################################################## + DateTime RelativeToday = clientTimeStamp.Date; + DateTime RelativeNow = clientTimeStamp.DateTime; -/* -################################################################################################### -Javascript version of this taken from most recent grid code: + // ############################################################################################################################################################# -// //////////////////// -// // -// function untokenizeListView(lvJson) { -// //if it has one or more tokens -// //iterate the array and build a new array with substituted tokens with the correct date and time in them - -// //format of a date token filter -// //[{"fld":"widgetname"},{"fld":"widgetstartdate","filter":{"items":[{"op":"=","value":"*past90days*","token":true}]}},{"fld":"widgetenddate"}] -// if (lvJson == null) { -// return lvJson; -// } -// //See if it has any date tokens -// if (lvJson.indexOf('"token":true') == -1) { -// return lvJson; -// } - -// //we have one or more tokens, substitute them in the filter array -// let ret = []; -// let lv = JSON.parse(lvJson); - -// //iterate the incoming and copy to the outgoing directly -// //except if a date token filter then substitute our own filter object in place -// for (let ilv = 0; ilv < lv.length; ilv++) { -// //listview object -// let lvo = lv[ilv]; -// //instantiate return object -// let reto = {}; -// //copy over field name to return object -// reto.fld = lvo.fld; -// //sort? -// if (lvo.sort) { -// reto.sort = lvo.sort; -// } -// //does it have a filter? -// if (lvo.filter) { -// //yes, so copy / transform as required - -// //create an empty filter items array on return object -// reto.filter = { items: [] }; - -// //"any" property set? -// if (lvo.filter.any) { -// reto.filter.any = true; -// } - -// //iterate the filter items in the source lvo object -// for (let j = 0; j < lvo.filter.items.length; j++) { -// //get this filter item -// let fi = lvo.filter.items[j]; -// //no token shortcut -// if (!fi.token) { -// //just copy it out -// reto.filter.items.push(fi); -// } else { -// //it has a date token so let's build it out -// //filter item value contains the token, op is always equals -// let filterDates = relativeDatefilterCalculator.tokenToDates(fi.value); -// //create and add a new filter item for each not undefined value -// //{ after: undefined, before: undefined } -// //AFTER DATE? -// if (filterDates.after) { -// reto.filter.items.push({ -// op: ">", //was GreaterThanOrEqualTo but that doesn't make sense, it's only greater than was seeing wrong return data as relative date filter already adjusts for boundaries -// value: filterDates.after -// }); -// } -// //BEFORE DATE? -// if (filterDates.before) { -// reto.filter.items.push({ -// op: "<", //was LessThanOrEqualTo but see above for after ===-----^ -// value: filterDates.before -// }); -// } -// } -// } - -// //end of has filter if condition -// } - -// //push the return object into the return array -// ret.push(reto); -// //end of iterate lv loop -// } - -// return JSON.stringify(ret); -// } //[{"fld":"widgetname"},{"fld":"widgetstartdate","filter":{"items":[{"op":"=","value":"*past90days*","token":true}]}},{"fld":"widgetenddate"}] - -############################################################################################################################################################# - -Last working server date token filter code from revision 2612 feb 7 2020 + // Last working server date token filter code from revision 2612 feb 7 2020 - //HOWEVER, if it's a relative date filter TOKEN like "nextMonth" then the users time zone offset will be taken into consideration - - //So this is the core date time to work off of - DateTime RelativeToday = DateTime.Today; - DateTime RelativeNow = DateTime.Now; - // ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger("FilterSqlCriteriaBuilder::DataFilterToColumnCriteria"); - // log.LogInformation("RelativeToday (before adjustment):"); - // log.LogInformation(RelativeToday.ToString()); - // log.LogInformation("RelativeNow (before adjustment):"); - // log.LogInformation(RelativeNow.ToString()); - - - if (sValue.StartsWith("{[") && sValue.EndsWith("]}")) + if (sValue.StartsWith("*") && sValue.EndsWith("*")) { - + //Need to adjust RelativeToday to users time frame //Fetch useroptions object and relative time offset @@ -571,7 +470,7 @@ Last working server date token filter code from revision 2612 feb 7 2020 switch (sValue) { //Case 402 - case DataListFilterSpecialToken.Yesterday: + case "*yesterday*": //Between Day before yesterday at midnight and yesterday at midnight dtAfter = RelativeToday.AddDays(-1); dtAfter = dtAfter.AddSeconds(-1); @@ -579,13 +478,13 @@ Last working server date token filter code from revision 2612 feb 7 2020 BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.Today: + case "*today*": //Between yesterday at midnight and tommorow at midnight dtAfter = RelativeToday.AddSeconds(-1); dtBefore = RelativeToday.AddDays(1); BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.Tomorrow: + case "*tomorrow*": //Between Tonight at midnight and day after tommorow at midnight dtAfter = RelativeToday.AddDays(1); dtAfter = dtAfter.AddSeconds(-1); @@ -594,7 +493,7 @@ Last working server date token filter code from revision 2612 feb 7 2020 break; //Case 402 - case DataListFilterSpecialToken.LastWeek: + case "*lastweek*": //Between two Sundays ago at midnight and last sunday at midnight dtAfter = RelativeToday; @@ -614,7 +513,7 @@ Last working server date token filter code from revision 2612 feb 7 2020 break; - case DataListFilterSpecialToken.ThisWeek: + case "*thisweek*": //Between Sunday at midnight and Next sunday at midnight dtAfter = RelativeToday; //go backwards to monday @@ -641,7 +540,7 @@ Last working server date token filter code from revision 2612 feb 7 2020 BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.NextWeek: + case "*nextweek*": //Between Next Sunday at midnight and Next Next sunday at midnight dtAfter = RelativeToday; @@ -664,7 +563,7 @@ Last working server date token filter code from revision 2612 feb 7 2020 BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.LastMonth: + case "*lastmonth*": //start with the first day of this month dtAfter = new DateTime(RelativeToday.Year, RelativeToday.Month, 1, RelativeToday.Hour, RelativeToday.Minute, 00); //subtract a Month @@ -680,7 +579,7 @@ Last working server date token filter code from revision 2612 feb 7 2020 BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.ThisMonth: + case "*thismonth*": //start with the first day of this month dtAfter = new DateTime(RelativeToday.Year, RelativeToday.Month, 1, RelativeToday.Hour, RelativeToday.Minute, 00); @@ -693,7 +592,7 @@ Last working server date token filter code from revision 2612 feb 7 2020 BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.NextMonth: + case "*nextmonth*": //start with the first day of this month dtAfter = new DateTime(RelativeToday.Year, RelativeToday.Month, 1, RelativeToday.Hour, RelativeToday.Minute, 00); //Add a Month @@ -706,7 +605,7 @@ Last working server date token filter code from revision 2612 feb 7 2020 dtAfter = dtAfter.AddSeconds(-1); BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.FourteenDayWindow: + case "*14daywindow*": //start with today zero hour dtAfter = new DateTime(RelativeToday.Year, RelativeToday.Month, RelativeToday.Day, RelativeToday.Hour, RelativeToday.Minute, 00); dtAfter = dtAfter.AddDays(-7); @@ -723,21 +622,21 @@ Last working server date token filter code from revision 2612 feb 7 2020 //case 2067 ADDITIONAL DATE RANGES ************ - case DataListFilterSpecialToken.Past: + case "*past*": //Forever up to Now dtAfter = new DateTime(1753, 1, 2, 00, 00, 00); dtBefore = DateTime.UtcNow; BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.Future: + case "*future*": //From Now to forever (999 years from now) dtAfter = DateTime.UtcNow; dtBefore = DateTime.UtcNow.AddYears(999); BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.LastYear: + case "*lastyear*": //From zero hour january 1 a year ago dtAfter = new DateTime(RelativeNow.AddYears(-1).Year, 1, 1, 0, 0, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); //To zero hour January 1 this year @@ -745,7 +644,7 @@ Last working server date token filter code from revision 2612 feb 7 2020 BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.ThisYear: + case "*thisyear*": //From zero hour january 1 this year dtAfter = new DateTime(RelativeNow.Year, 1, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); //To zero hour Jan 1 next year @@ -753,7 +652,7 @@ Last working server date token filter code from revision 2612 feb 7 2020 BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.InTheLast3Months: + case "*last3months*": //From Now minus 3 months dtAfter = DateTime.UtcNow.AddMonths(-3); //To Now @@ -761,7 +660,7 @@ Last working server date token filter code from revision 2612 feb 7 2020 BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.InTheLast6Months: + case "*last6months*": //From Now minus 6 months dtAfter = DateTime.UtcNow.AddMonths(-6); //To Now @@ -769,7 +668,7 @@ Last working server date token filter code from revision 2612 feb 7 2020 BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.InTheLastYear: + case "*pastyear*": //within the prior 365 days before today //From Now minus 365 days dtAfter = DateTime.UtcNow.AddDays(-365); //To Now @@ -777,33 +676,26 @@ Last working server date token filter code from revision 2612 feb 7 2020 BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - //======================= - //NEW ONES FOR RAVEN - - case DataListFilterSpecialToken.YearToDate: - //From zero hour january 1 this year - dtAfter = new DateTime(RelativeNow.Year, 1, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); ; - //To now - dtBefore = RelativeNow; - BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); - break; - - case DataListFilterSpecialToken.Past90Days: + case "*past90days*": //From Now minus 90 days dtAfter = DateTime.UtcNow.AddDays(-90); //To Now dtBefore = DateTime.UtcNow; BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.Past30Days: + case "*past30days*": //From Now minus 30 days dtAfter = DateTime.UtcNow.AddDays(-30); //To Now dtBefore = DateTime.UtcNow; BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.Past24Hours: + case "*past7days*": + throw new System.NotImplementedException("DATE TOKEN NOT IMPLEMENTED YET"); + break; + + case "*past24hours*": //From Now minus 24 hours dtAfter = DateTime.UtcNow.AddHours(-24); //To Now @@ -811,7 +703,11 @@ Last working server date token filter code from revision 2612 feb 7 2020 BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.January: + case "*past6hours*": + throw new System.NotImplementedException("DATE TOKEN NOT IMPLEMENTED YET"); + break; + + case "*january*": //From zero hour january 1 this year dtAfter = new DateTime(RelativeNow.Year, 1, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); //To zero hour feb 1 this year @@ -819,73 +715,86 @@ Last working server date token filter code from revision 2612 feb 7 2020 BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.February: + case "*february*": dtAfter = new DateTime(RelativeNow.Year, 2, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); dtBefore = new DateTime(RelativeNow.Year, 3, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.March: + case "*march*": dtAfter = new DateTime(RelativeNow.Year, 3, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); dtBefore = new DateTime(RelativeNow.Year, 4, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.April: + case "*april*": dtAfter = new DateTime(RelativeNow.Year, 4, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); dtBefore = new DateTime(RelativeNow.Year, 5, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.May: + case "*may*": dtAfter = new DateTime(RelativeNow.Year, 5, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); dtBefore = new DateTime(RelativeNow.Year, 6, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.June: + case "*june*": dtAfter = new DateTime(RelativeNow.Year, 6, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); dtBefore = new DateTime(RelativeNow.Year, 7, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.July: + case "*july*": dtAfter = new DateTime(RelativeNow.Year, 7, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); dtBefore = new DateTime(RelativeNow.Year, 8, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.August: + case "*august*": dtAfter = new DateTime(RelativeNow.Year, 8, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); dtBefore = new DateTime(RelativeNow.Year, 9, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.September: + case "*september*": dtAfter = new DateTime(RelativeNow.Year, 9, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); dtBefore = new DateTime(RelativeNow.Year, 10, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.October: + case "*october*": dtAfter = new DateTime(RelativeNow.Year, 10, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); dtBefore = new DateTime(RelativeNow.Year, 11, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.November: + case "*november*": dtAfter = new DateTime(RelativeNow.Year, 11, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); dtBefore = new DateTime(RelativeNow.Year, 12, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; - case DataListFilterSpecialToken.December: + case "*december*": //From zero hour dec 1 this year dtAfter = new DateTime(RelativeNow.Year, 12, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); //To zero hour Jan 1 next year dtBefore = new DateTime(RelativeNow.AddYears(1).Year, 1, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); break; + case "*lastyearlastmonth*": + throw new System.NotImplementedException("DATE TOKEN NOT IMPLEMENTED YET"); + break; + + case "*lastyearthismonth*": + throw new System.NotImplementedException("DATE TOKEN NOT IMPLEMENTED YET"); + break; + + case "*lastyearnextmonth*": + throw new System.NotImplementedException("DATE TOKEN NOT IMPLEMENTED YET"); + break; + + default: throw new System.ArgumentOutOfRangeException("TOKEN", sOperator, "DataListSqlFilterCriteriaBuilder invalid filter TOKEN type [" + sValue + "] IN DATE_TIME"); @@ -897,82 +806,76 @@ Last working server date token filter code from revision 2612 feb 7 2020 } else { -*/ + #region Build criteria for date specified + //dates come in iso8601 UTC format from the client + //suitable for the database to handle as all database dates are in UTC + //Local display and parsing will be considered a CLIENT issue at all times + //so a simple parse should be sufficient + //https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings#Roundtrip + System.DateTime dtData = DateTime.Parse(sValue); + + //THis is because we don't want milliseconds to alter the value in any way, AyaNova resolution for time is seconds not milliseconds to allow for some sloppiness + //so no date is exact and we work around that with ranges that rule out milliseconds affecting query + //also this needs to work in conjunction with client filters for date ranges that provide a value one second before the range in question as START timestamp + //and exactly the end of range in question as END timestamp + string sDateValueWithMaxMilliseconds = PostgresDateFormat(MaxMilliseconds(dtData)); + string sDateValueWithZeroMilliseconds = PostgresDateFormat(ZeroMilliseconds(dtData)); + + switch (sOperator) + { + case DataListFilterComparisonOperator.Equality: + sb.Append(">='"); + sb.Append(sDateValueWithZeroMilliseconds); + sb.Append("' AND "); + sb.Append(SqlColumnNameToFilter); + sb.Append(" "); + sb.Append("<='"); + sb.Append(sDateValueWithMaxMilliseconds); + sb.Append("'"); + break; + + case DataListFilterComparisonOperator.GreaterThan: + sb.Append(">'"); + sb.Append(sDateValueWithMaxMilliseconds); + sb.Append("'"); + break; + + case DataListFilterComparisonOperator.GreaterThanOrEqualTo: + sb.Append(">='"); + sb.Append(sDateValueWithZeroMilliseconds); + sb.Append("'"); + break; + case DataListFilterComparisonOperator.LessThan: + sb.Append("<'"); + sb.Append(sDateValueWithZeroMilliseconds); + sb.Append("'"); + break; + case DataListFilterComparisonOperator.LessThanOrEqualTo: + sb.Append("<='"); + sb.Append(sDateValueWithMaxMilliseconds); + sb.Append("'"); + break; + + case DataListFilterComparisonOperator.NotEqual: + sb.Append("<'"); + sb.Append(sDateValueWithZeroMilliseconds); + sb.Append("' OR "); + sb.Append(SqlColumnNameToFilter); + sb.Append(" "); + sb.Append(">'"); + sb.Append(sDateValueWithMaxMilliseconds); + sb.Append("'"); + + break; + default: + throw new System.ArgumentOutOfRangeException("OPERATOR_TYPE", sOperator, "DataListSqlFilterCriteriaBuilder unhandled operator type [" + sOperator + "] IN DATE_TIME"); - - //Note: it is assumed all dates come into here from the CLIENT in UTC iso8601 format - //suitable for the database to handle as all database dates are in UTC - //Local display and parsing will be considered a CLIENT issue at all times - - #region Build criteria for date specified - //RAVEN NOTE: it is my intention that dates come in iso8601 UTC format from the client - //so a simple parse should be sufficient - //https://docs.microsoft.com/en-us/dotnet/standard/base-types/standard-date-and-time-format-strings#Roundtrip - System.DateTime dtData = DateTime.Parse(sValue); - - //THis is because we don't want milliseconds to alter the value in any way, AyaNova resolution for time is seconds not milliseconds to allow for some sloppiness - //so no date is exact and we work around that with ranges that rule out milliseconds affecting query - //also this needs to work in conjunction with client filters for date ranges that provide a value one second before the range in question as START timestamp - //and exactly the end of range in question as END timestamp - string sDateValueWithMaxMilliseconds = PostgresDateFormat(MaxMilliseconds(dtData)); - string sDateValueWithZeroMilliseconds = PostgresDateFormat(ZeroMilliseconds(dtData)); - - switch (sOperator) - { - case DataListFilterComparisonOperator.Equality: - sb.Append(">='"); - sb.Append(sDateValueWithZeroMilliseconds); - sb.Append("' AND "); - sb.Append(SqlColumnNameToFilter); - sb.Append(" "); - sb.Append("<='"); - sb.Append(sDateValueWithMaxMilliseconds); - sb.Append("'"); - break; - - case DataListFilterComparisonOperator.GreaterThan: - sb.Append(">'"); - sb.Append(sDateValueWithMaxMilliseconds); - sb.Append("'"); - break; - - case DataListFilterComparisonOperator.GreaterThanOrEqualTo: - sb.Append(">='"); - sb.Append(sDateValueWithZeroMilliseconds); - sb.Append("'"); - break; - case DataListFilterComparisonOperator.LessThan: - sb.Append("<'"); - sb.Append(sDateValueWithZeroMilliseconds); - sb.Append("'"); - break; - case DataListFilterComparisonOperator.LessThanOrEqualTo: - sb.Append("<='"); - sb.Append(sDateValueWithMaxMilliseconds); - sb.Append("'"); - break; - - case DataListFilterComparisonOperator.NotEqual: - sb.Append("<'"); - sb.Append(sDateValueWithZeroMilliseconds); - sb.Append("' OR "); - sb.Append(SqlColumnNameToFilter); - sb.Append(" "); - sb.Append(">'"); - sb.Append(sDateValueWithMaxMilliseconds); - sb.Append("'"); - - break; - default: - throw new System.ArgumentOutOfRangeException("OPERATOR_TYPE", sOperator, "DataListSqlFilterCriteriaBuilder unhandled operator type [" + sOperator + "] IN DATE_TIME"); - - + } + #endregion } - #endregion - //} } break; case UiFieldDataType.Enum://enums are just ints to the db, but it's a special type so the client can recognize it @@ -1136,3 +1039,1114 @@ Last working server date token filter code from revision 2612 feb 7 2020 }//eoc }//ens +/* + + +Javascript relative date calculator +///////////////////////////////////////////////////////////////////////////////////////////////////////////// +// Xeslint-disable +//////////////////////////////////////////////////////////////////////////////////////////////////////////// + +///////////////////////////////// +// Convert a date token to local +// date range to UTC for server +// dataListView consumption +// +export default { + /////////////////////////////// + // token to date range + // + tokenToDates: function(token) { + if (token == null || token.length == 0) { + throw new Error( + "relative-date-filter-calculator: date token is null or empty" + ); + } + + //return object contains the two dates that encompass the time period + //the token represents to the local browser time zone but in UTC + //and iso8601 format + + //NOTE: it's valid for one of the two ret values might be undefined as it's valid to have a single date for + //Past or Future + let ret = { after: undefined, before: undefined }; + let dtNow = window.$gz.DateTime.local(); + let dtToday = window.$gz.DateTime.local(dtNow.year, dtNow.month, dtNow.day); + let dtAfter = null; + let dtBefore = null; + + switch (token) { + case "*yesterday*": + //Between Day before yesterday at midnight and yesterday at midnight + ret.after = dtToday + .plus({ days: -1, seconds: -1 }) + .toUTC() + .toString(); + ret.before = dtToday.toUTC().toString(); + break; + + case "*today*": + //Between yesterday at midnight and tommorow at midnight + ret.after = dtToday + .plus({ seconds: -1 }) + .toUTC() + .toString(); + ret.before = dtToday + .plus({ days: 1 }) + .toUTC() + .toString(); + break; + + case "*tomorrow*": + //Between Tonight at midnight and day after tommorow at midnight + ret.after = dtToday + .plus({ days: 1, seconds: -1 }) + .toUTC() + .toString(); + ret.before = dtToday + .plus({ days: 2 }) + .toUTC() + .toString(); + break; + + case "*lastweek*": + //Between two Sundays ago at midnight and last sunday at midnight + + //go back a week + dtAfter = dtToday.plus({ days: -7 }); + //go backwards to Sunday (In Luxon Monday is 1, Sunday is 7) + while (dtAfter.weekday != 7) { + dtAfter = dtAfter.plus({ days: -1 }); + } + //go to very start of eighth dayahead + dtBefore = dtAfter.plus({ days: 8 }); + //remove a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*thisweek*": + //Between Sunday at midnight and Next sunday at midnight + + //Start with today + dtAfter = dtToday; + //SET dtAfter to Monday start of this week + //go backwards to monday (In Luxon Monday is 1, Sunday is 7) + while (dtAfter.weekday != 1) { + dtAfter = dtAfter.plus({ days: -1 }); + } + //Now go back to sunday last second + dtAfter = dtAfter.plus({ seconds: -1 }); + + //Start with today + dtBefore = dtToday; + + //SET dtBefore to next monday + //is it monday now? + if (dtBefore.weekday == 1) { + //Monday today? then go to next monday + dtBefore = dtBefore.plus({ days: 7 }); + } else { + //Find next monday... + while (dtBefore.weekday != 1) { + dtBefore = dtBefore.plus({ days: 1 }); + } + } + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*nextweek*": + //Between Next Sunday at midnight and Next Next sunday at midnight + + //Start with today + dtAfter = dtToday; + //If today is monday skip over it first, we're looking for *next* monday, not this one + if (dtAfter.weekday == 1) { + dtAfter = dtAfter.plus({ days: 1 }); + } + + //go forwards to next monday 12:00am (In Luxon Monday is 1, Sunday is 7) + while (dtAfter.weekday != 1) { + dtAfter = dtAfter.plus({ days: 1 }); + } + //Now go back to sunday last second + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set dtBefore 7 days ahead of dtAfter + //(sb BEFORE two mondays from now at zero hour so need to add a second due to prior removal of a second to make sunday) + dtBefore = dtAfter.plus({ days: 7, seconds: 1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*lastmonth*": + //start with the first day of this month + dtAfter = window.$gz.DateTime.local(dtNow.year, dtNow.month, 1); + //subtract a Month + dtAfter = dtAfter.plus({ months: -1 }); + //Add one month to dtAfter to get end date + dtBefore = dtAfter.plus({ months: 1 }); + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*thismonth*": + //start with the first day of this month + dtAfter = window.$gz.DateTime.local(dtNow.year, dtNow.month, 1); + //Add one month to dtAfter to get end date + dtBefore = dtAfter.plus({ months: 1 }); + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*nextmonth*": + //start with the first day of this month + dtAfter = window.$gz.DateTime.local(dtNow.year, dtNow.month, 1); + + //add a month + dtAfter = dtAfter.plus({ months: 1 }); + + //Add one month to dtAfter to get end date + dtBefore = dtAfter.plus({ months: 1 }); + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*14daywindow*": + //Start with today + dtAfter = dtToday; + + //subtract 7 days + dtAfter = dtAfter.plus({ days: -7 }); + + //Add 15 days to dtAfter to get end date + dtBefore = dtAfter.plus({ days: 15 }); + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*past*": + //Any time before Now + //set return values from calculated values + ret.after = undefined; + ret.before = dtNow.toUTC().toString(); + break; + + case "*future*": + //Any time after Now + //set return values from calculated values + ret.after = dtNow.toUTC().toString(); + ret.before = undefined; + break; + + case "*lastyear*": + //"last year" means prior calendar year from start of january to end of december + //start with the first day of this year + dtAfter = window.$gz.DateTime.local(dtNow.year); + + //subtract a year + dtAfter = dtAfter.plus({ years: -1 }); + + //Before zero hour january 1st this year + dtBefore = window.$gz.DateTime.local(dtNow.year); + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*thisyear*": + //From zero hour january 1 this year (minus a second) to zero hour jan 1 next year + //start with the first day of this year + dtAfter = window.$gz.DateTime.local(dtNow.year); + + //Before zero hour january 1st next year + dtBefore = window.$gz.DateTime.local(dtNow.year); + dtBefore = dtBefore.plus({ years: 1 }); + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*last3months*": + //From Now minus 3 months + dtAfter = dtToday.plus({ months: -3 }); + + //Before now + dtBefore = dtNow; + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*last6months*": + //From Now minus 6 months + dtAfter = dtToday.plus({ months: -6 }); + + //Before now + dtBefore = dtNow; + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*pastyear*": //within the prior 365 days before today + //From Now minus 365 days + dtAfter = dtToday.plus({ days: -365 }); + + //Before now + dtBefore = dtNow; + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*past90days*": + //From Now minus 90 days + dtAfter = dtNow.plus({ days: -90 }); + + //Before now + dtBefore = dtNow; + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*past30days*": + //From Now minus 30 days + dtAfter = dtNow.plus({ days: -30 }); + + //Before now + dtBefore = dtNow; + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*past7days*": + //From Now minus 7 days + dtAfter = dtNow.plus({ days: -7 }); + + //Before now + dtBefore = dtNow; + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*past24hours*": + //From Now minus 24 hours + dtAfter = dtNow.plus({ hours: -24 }); + + //Before now + dtBefore = dtNow; + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*past6hours*": + //From Now minus 6 hours + dtAfter = dtNow.plus({ hours: -6 }); + + //Before now + dtBefore = dtNow; + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + /////////////////////////////////////////////////////////////////////////// + case "*january*": + //This year specific month (month is 1 based) + dtAfter = window.$gz.DateTime.local(dtNow.year, 1, 1); + + //Add one month to dtAfter to get end date + dtBefore = dtAfter.plus({ months: 1 }); + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*february*": + //This year specific month (month is 1 based) + dtAfter = window.$gz.DateTime.local(dtNow.year, 2, 1); + + //Add one month to dtAfter to get end date + dtBefore = dtAfter.plus({ months: 1 }); + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*march*": + //This year specific month (month is 1 based) + dtAfter = window.$gz.DateTime.local(dtNow.year, 3, 1); + + //Add one month to dtAfter to get end date + dtBefore = dtAfter.plus({ months: 1 }); + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*april*": + //This year specific month (month is 1 based) + dtAfter = window.$gz.DateTime.local(dtNow.year, 4, 1); + + //Add one month to dtAfter to get end date + dtBefore = dtAfter.plus({ months: 1 }); + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*may*": + //This year specific month (month is 1 based) + dtAfter = window.$gz.DateTime.local(dtNow.year, 5, 1); + + //Add one month to dtAfter to get end date + dtBefore = dtAfter.plus({ months: 1 }); + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*june*": + //This year specific month (month is 1 based) + dtAfter = window.$gz.DateTime.local(dtNow.year, 6, 1); + + //Add one month to dtAfter to get end date + dtBefore = dtAfter.plus({ months: 1 }); + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*july*": + //This year specific month (month is 1 based) + dtAfter = window.$gz.DateTime.local(dtNow.year, 7, 1); + + //Add one month to dtAfter to get end date + dtBefore = dtAfter.plus({ months: 1 }); + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*august*": + //This year specific month (month is 1 based) + dtAfter = window.$gz.DateTime.local(dtNow.year, 8, 1); + + //Add one month to dtAfter to get end date + dtBefore = dtAfter.plus({ months: 1 }); + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*september*": + //This year specific month (month is 1 based) + dtAfter = window.$gz.DateTime.local(dtNow.year, 9, 1); + + //Add one month to dtAfter to get end date + dtBefore = dtAfter.plus({ months: 1 }); + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*october*": + //This year specific month (month is 1 based) + dtAfter = window.$gz.DateTime.local(dtNow.year, 10, 1); + + //Add one month to dtAfter to get end date + dtBefore = dtAfter.plus({ months: 1 }); + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*november*": + //This year specific month (month is 1 based) + dtAfter = window.$gz.DateTime.local(dtNow.year, 11, 1); + + //Add one month to dtAfter to get end date + dtBefore = dtAfter.plus({ months: 1 }); + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*december*": + //This year specific month (month is 1 based) + dtAfter = window.$gz.DateTime.local(dtNow.year, 12, 1); + + //Add one month to dtAfter to get end date + dtBefore = dtAfter.plus({ months: 1 }); + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*lastyearlastmonth*": + //start with the first day of this month + dtAfter = window.$gz.DateTime.local(dtNow.year, dtNow.month, 1); + //subtract a Year and a Month + dtAfter = dtAfter.plus({ years: -1, months: -1 }); + //Add one month to dtAfter to get end date + dtBefore = dtAfter.plus({ months: 1 }); + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*lastyearthismonth*": + //start with the first day of this month + dtAfter = window.$gz.DateTime.local(dtNow.year, dtNow.month, 1); + //subtract a Year + dtAfter = dtAfter.plus({ years: -1 }); + //Add one month to dtAfter to get end date + dtBefore = dtAfter.plus({ months: 1 }); + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + case "*lastyearnextmonth*": + //start with the first day of this month + dtAfter = window.$gz.DateTime.local(dtNow.year, dtNow.month, 1); + + //subtract a year, add a month + dtAfter = dtAfter.plus({ years: -1, months: 1 }); + + //Add one month to dtAfter to get end date + dtBefore = dtAfter.plus({ months: 1 }); + + //move after back a second for boundary + dtAfter = dtAfter.plus({ seconds: -1 }); + + //set return values from calculated values + ret.after = dtAfter.toUTC().toString(); + ret.before = dtBefore.toUTC().toString(); + break; + + default: + throw new Error( + "relative-date-time-filter-calculater: Date token [" + + token + + "] was not recognized" + ); + //-------------------------- + } + + return ret; + } + + + + { name: vm.$ay.t("DateRangeJanuary"), id: "*january*" }, + { name: vm.$ay.t("DateRangeFebruary"), id: "*february*" }, + { name: vm.$ay.t("DateRangeMarch"), id: "*march*" }, + { name: vm.$ay.t("DateRangeApril"), id: "*april*" }, + { name: vm.$ay.t("DateRangeMay"), id: "*may*" }, + { name: vm.$ay.t("DateRangeJune"), id: "*june*" }, + { name: vm.$ay.t("DateRangeJuly"), id: "*july*" }, + { name: vm.$ay.t("DateRangeAugust"), id: "*august*" }, + { name: vm.$ay.t("DateRangeSeptember"), id: "*september*" }, + { name: vm.$ay.t("DateRangeOctober"), id: "*october*" }, + { name: vm.$ay.t("DateRangeNovember"), id: "*november*" }, + { name: vm.$ay.t("DateRangeDecember"), id: "*december*" }, + { + name: vm.$ay.t("DateRangePreviousYearThisMonth"), + id: "*lastyearthismonth*" + }, + { + name: vm.$ay.t("DateRangePreviousYearLastMonth"), + id: "*lastyearlastmonth*" + }, + { + name: vm.$ay.t("DateRangePreviousYearNextMonth"), + id: "*lastyearnextmonth*" + } + + + //new functions above here +}; +//LUXON MATH: https://moment.github.io/luxon/docs/manual/zones.html#math-across-dsts +//https://moment.github.io/luxon/docs/manual/math.html +//luxon api ref: https://moment.github.io/luxon/docs/class/src/datetime.js~DateTime.html + +// //############################################################### OLD SERVER FILTERING CODE ########################## + +// //HOWEVER, if it's a relative date filter TOKEN like "nextMonth" then the users time zone offset will be taken into consideration + +// //So this is the core date time to work off of +// DateTime RelativeToday = DateTime.Today; +// DateTime RelativeNow = DateTime.Now; +// // ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger("FilterSqlCriteriaBuilder::DataFilterToColumnCriteria"); +// // log.LogInformation("RelativeToday (before adjustment):"); +// // log.LogInformation(RelativeToday.ToString()); +// // log.LogInformation("RelativeNow (before adjustment):"); +// // log.LogInformation(RelativeNow.ToString()); + +// if (sValue.StartsWith("{[") && sValue.EndsWith("]}")) +// { + +// //Need to adjust RelativeToday to users time frame +// //Fetch useroptions object and relative time offset +// //See servers spec doc core-locale-currency-numbers-time-and-dates.txt for details about why this is necessary to be done this way +// AyaNova.Models.AyContext ct = AyaNova.Util.ServiceProviderProvider.DBContext; +// let u = ct.User.AsNoTracking().Where(a => a.Id == userId).Select(m => new { tz = m.UserOptions.TimeZoneOffset }).First(); + +// //Add this value to any time's hours to convert to user local time +// Double TimeZoneAdjustment = ((double)u.tz) * -1; + +// //Stock times used for many of the tokens: +// RelativeToday = RelativeToday.AddHours(TimeZoneAdjustment);//flip the sign to adjust towards UTC +// RelativeNow = RelativeNow.AddHours(TimeZoneAdjustment);//flip the sign to adjust towards UTC + +// //TESTING: +// //LOG THE CRIT AND QUERY +// // ILogger log = AyaNova.Util.ApplicationLogging.CreateLogger("FilterSqlCriteriaBuilder::DataFilterToColumnCriteria"); +// // log.LogInformation("RelativeToday (adjusted):"); +// // log.LogInformation(RelativeToday.ToString()); +// // log.LogInformation("RelativeNow (adjusted):"); +// // log.LogInformation(RelativeNow.ToString()); +// // log.LogInformation("Offset used:"); +// // log.LogInformation(u.tz.ToString()); + +// #region Build criteria for date RANGE TOKEN specified +// //Used as the basis point +// System.DateTime dtAfter; +// System.DateTime dtBefore; +// switch (sValue) +// { +// //Case 402 +// case DataListFilterSpecialToken.Yesterday: +// //Between Day before yesterday at midnight and yesterday at midnight +// dtAfter = RelativeToday.AddDays(-1); +// dtAfter = dtAfter.AddSeconds(-1); +// dtBefore = RelativeToday;//.AddDays(-1); +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.Today: +// //Between yesterday at midnight and tommorow at midnight +// dtAfter = RelativeToday.AddSeconds(-1); +// dtBefore = RelativeToday.AddDays(1); +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; +// case DataListFilterSpecialToken.Tomorrow: +// //Between Tonight at midnight and day after tommorow at midnight +// dtAfter = RelativeToday.AddDays(1); +// dtAfter = dtAfter.AddSeconds(-1); +// dtBefore = RelativeToday.AddDays(2); +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// //Case 402 +// case DataListFilterSpecialToken.LastWeek: +// //Between two Sundays ago at midnight and last sunday at midnight +// dtAfter = RelativeToday; + +// //go back a week +// dtAfter = dtAfter.AddDays(-7); + +// //go backwards to Sunday +// while (dtAfter.DayOfWeek != DayOfWeek.Sunday) +// dtAfter = dtAfter.AddDays(-1); + +// //go to very start of eighth dayahead +// dtBefore = dtAfter.AddDays(8); + +// dtAfter = dtAfter.AddSeconds(-1); + +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.ThisWeek: +// //Between Sunday at midnight and Next sunday at midnight +// dtAfter = RelativeToday; +// //go backwards to monday +// while (dtAfter.DayOfWeek != DayOfWeek.Monday) +// dtAfter = dtAfter.AddDays(-1); + +// //Now go back to sunday last second +// dtAfter = dtAfter.AddSeconds(-1); + +// dtBefore = RelativeToday; +// //go forwards to monday +// if (RelativeToday.DayOfWeek == DayOfWeek.Monday) +// { +// //Monday today? then go to next monday +// dtBefore = dtBefore.AddDays(7); +// } +// else +// { +// while (dtBefore.DayOfWeek != DayOfWeek.Monday) +// dtBefore = dtBefore.AddDays(1); +// } + +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; +// case DataListFilterSpecialToken.NextWeek: +// //Between Next Sunday at midnight and Next Next sunday at midnight +// dtAfter = RelativeToday; + +// //If today is monday skip over it first +// if (dtAfter.DayOfWeek == DayOfWeek.Monday) +// dtAfter = dtAfter.AddDays(1); + +// //go forwards to next monday +// while (dtAfter.DayOfWeek != DayOfWeek.Monday) +// dtAfter = dtAfter.AddDays(1); + +// //Now go back to sunday last second +// dtAfter = dtAfter.AddDays(-1); + +// //go seven days ahead +// dtBefore = dtAfter.AddDays(7); + +// //case 1155 +// dtAfter = dtAfter.AddSeconds(-1); + +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; +// case DataListFilterSpecialToken.LastMonth: +// //start with the first day of this month +// dtAfter = new DateTime(RelativeToday.Year, RelativeToday.Month, 1, RelativeToday.Hour, RelativeToday.Minute, 00); +// //subtract a Month +// dtAfter = dtAfter.AddMonths(-1); + +// //Add one month to dtAfter to get end date +// dtBefore = dtAfter.AddMonths(1); + +// //case 1155 +// dtAfter = dtAfter.AddSeconds(-1); + +// // 'yyyy-mm-ddTHH:MM:SS' + +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; +// case DataListFilterSpecialToken.ThisMonth: +// //start with the first day of this month +// dtAfter = new DateTime(RelativeToday.Year, RelativeToday.Month, 1, RelativeToday.Hour, RelativeToday.Minute, 00); + +// //Add one month to dtAfter to get end date +// dtBefore = dtAfter.AddMonths(1); + +// //case 1155 +// dtAfter = dtAfter.AddSeconds(-1); + +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.NextMonth: +// //start with the first day of this month +// dtAfter = new DateTime(RelativeToday.Year, RelativeToday.Month, 1, RelativeToday.Hour, RelativeToday.Minute, 00); +// //Add a Month +// dtAfter = dtAfter.AddMonths(1); + +// //Add one month to dtAfter to get end date +// dtBefore = dtAfter.AddMonths(1); + +// //case 1155 +// dtAfter = dtAfter.AddSeconds(-1); +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; +// case DataListFilterSpecialToken.FourteenDayWindow: +// //start with today zero hour +// dtAfter = new DateTime(RelativeToday.Year, RelativeToday.Month, RelativeToday.Day, RelativeToday.Hour, RelativeToday.Minute, 00); +// dtAfter = dtAfter.AddDays(-7); + +// //Add 15 days to get end date (zero hour so not really 15 full days) +// dtBefore = dtAfter.AddDays(15); + +// //case 1155 +// dtAfter = dtAfter.AddSeconds(-1); + +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// //case 2067 ADDITIONAL DATE RANGES ************ + +// case DataListFilterSpecialToken.Past: +// //Forever up to Now +// dtAfter = new DateTime(1753, 1, 2, 00, 00, 00); +// dtBefore = DateTime.UtcNow; +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.Future: +// //From Now to forever (999 years from now) +// dtAfter = DateTime.UtcNow; +// dtBefore = DateTime.UtcNow.AddYears(999); +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.LastYear: +// //From zero hour january 1 a year ago +// dtAfter = new DateTime(RelativeNow.AddYears(-1).Year, 1, 1, 0, 0, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); +// //To zero hour January 1 this year +// dtBefore = new DateTime(RelativeNow.Year, 1, 1, 0, 0, 00).AddHours(TimeZoneAdjustment); +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.ThisYear: +// //From zero hour january 1 this year +// dtAfter = new DateTime(RelativeNow.Year, 1, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); +// //To zero hour Jan 1 next year +// dtBefore = new DateTime(RelativeNow.AddYears(1).Year, 1, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.InTheLast3Months: +// //From Now minus 3 months +// dtAfter = DateTime.UtcNow.AddMonths(-3); +// //To Now +// dtBefore = DateTime.UtcNow; +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.InTheLast6Months: +// //From Now minus 6 months +// dtAfter = DateTime.UtcNow.AddMonths(-6); +// //To Now +// dtBefore = DateTime.UtcNow; +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.InTheLastYear: +// //From Now minus 365 days +// dtAfter = DateTime.UtcNow.AddDays(-365); +// //To Now +// dtBefore = DateTime.UtcNow; +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// //======================= +// //NEW ONES FOR RAVEN + +// case DataListFilterSpecialToken.YearToDate: +// //From zero hour january 1 this year +// dtAfter = new DateTime(RelativeNow.Year, 1, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); ; +// //To now +// dtBefore = RelativeNow; +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.Past90Days: +// //From Now minus 90 days +// dtAfter = DateTime.UtcNow.AddDays(-90); +// //To Now +// dtBefore = DateTime.UtcNow; +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; +// case DataListFilterSpecialToken.Past30Days: +// //From Now minus 30 days +// dtAfter = DateTime.UtcNow.AddDays(-30); +// //To Now +// dtBefore = DateTime.UtcNow; +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; +// case DataListFilterSpecialToken.Past24Hours: +// //From Now minus 24 hours +// dtAfter = DateTime.UtcNow.AddHours(-24); +// //To Now +// dtBefore = DateTime.UtcNow; +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.January: +// //From zero hour january 1 this year +// dtAfter = new DateTime(RelativeNow.Year, 1, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); +// //To zero hour feb 1 this year +// dtBefore = new DateTime(RelativeNow.Year, 2, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.February: +// dtAfter = new DateTime(RelativeNow.Year, 2, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); +// dtBefore = new DateTime(RelativeNow.Year, 3, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.March: +// dtAfter = new DateTime(RelativeNow.Year, 3, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); +// dtBefore = new DateTime(RelativeNow.Year, 4, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.April: +// dtAfter = new DateTime(RelativeNow.Year, 4, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); +// dtBefore = new DateTime(RelativeNow.Year, 5, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.May: +// dtAfter = new DateTime(RelativeNow.Year, 5, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); +// dtBefore = new DateTime(RelativeNow.Year, 6, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.June: +// dtAfter = new DateTime(RelativeNow.Year, 6, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); +// dtBefore = new DateTime(RelativeNow.Year, 7, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.July: +// dtAfter = new DateTime(RelativeNow.Year, 7, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); +// dtBefore = new DateTime(RelativeNow.Year, 8, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.August: +// dtAfter = new DateTime(RelativeNow.Year, 8, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); +// dtBefore = new DateTime(RelativeNow.Year, 9, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.September: +// dtAfter = new DateTime(RelativeNow.Year, 9, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); +// dtBefore = new DateTime(RelativeNow.Year, 10, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.October: +// dtAfter = new DateTime(RelativeNow.Year, 10, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); +// dtBefore = new DateTime(RelativeNow.Year, 11, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.November: +// dtAfter = new DateTime(RelativeNow.Year, 11, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); +// dtBefore = new DateTime(RelativeNow.Year, 12, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// case DataListFilterSpecialToken.December: +// //From zero hour dec 1 this year +// dtAfter = new DateTime(RelativeNow.Year, 12, 1, 00, 00, 00).AddSeconds(-1).AddHours(TimeZoneAdjustment); +// //To zero hour Jan 1 next year +// dtBefore = new DateTime(RelativeNow.AddYears(1).Year, 1, 1, 00, 00, 00).AddHours(TimeZoneAdjustment); +// BuildBetweenTwoDatesFragment(SqlColumnNameToFilter, sb, dtAfter, dtBefore); +// break; + +// +// //----- +// } + +// #endregion +// } +// else +// { + +################################################################################################### +Javascript version of date de-tokenizer taken from most recent grid code: + +// //////////////////// +// // +// function untokenizeListView(lvJson) { +// //if it has one or more tokens +// //iterate the array and build a new array with substituted tokens with the correct date and time in them + +// //format of a date token filter +// //[{"fld":"widgetname"},{"fld":"widgetstartdate","filter":{"items":[{"op":"=","value":"*past90days*","token":true}]}},{"fld":"widgetenddate"}] +// if (lvJson == null) { +// return lvJson; +// } +// //See if it has any date tokens +// if (lvJson.indexOf('"token":true') == -1) { +// return lvJson; +// } + +// //we have one or more tokens, substitute them in the filter array +// let ret = []; +// let lv = JSON.parse(lvJson); + +// //iterate the incoming and copy to the outgoing directly +// //except if a date token filter then substitute our own filter object in place +// for (let ilv = 0; ilv < lv.length; ilv++) { +// //listview object +// let lvo = lv[ilv]; +// //instantiate return object +// let reto = {}; +// //copy over field name to return object +// reto.fld = lvo.fld; +// //sort? +// if (lvo.sort) { +// reto.sort = lvo.sort; +// } +// //does it have a filter? +// if (lvo.filter) { +// //yes, so copy / transform as required + +// //create an empty filter items array on return object +// reto.filter = { items: [] }; + +// //"any" property set? +// if (lvo.filter.any) { +// reto.filter.any = true; +// } + +// //iterate the filter items in the source lvo object +// for (let j = 0; j < lvo.filter.items.length; j++) { +// //get this filter item +// let fi = lvo.filter.items[j]; +// //no token shortcut +// if (!fi.token) { +// //just copy it out +// reto.filter.items.push(fi); +// } else { +// //it has a date token so let's build it out +// //filter item value contains the token, op is always equals +// let filterDates = relativeDatefilterCalculator.tokenToDates(fi.value); +// //create and add a new filter item for each not undefined value +// //{ after: undefined, before: undefined } +// //AFTER DATE? +// if (filterDates.after) { +// reto.filter.items.push({ +// op: ">", //was GreaterThanOrEqualTo but that doesn't make sense, it's only greater than was seeing wrong return data as relative date filter already adjusts for boundaries +// value: filterDates.after +// }); +// } +// //BEFORE DATE? +// if (filterDates.before) { +// reto.filter.items.push({ +// op: "<", //was LessThanOrEqualTo but see above for after ===-----^ +// value: filterDates.before +// }); +// } +// } +// } + +// //end of has filter if condition +// } + +// //push the return object into the return array +// ret.push(reto); +// //end of iterate lv loop +// } + +// return JSON.stringify(ret); +// } //[{"fld":"widgetname"},{"fld":"widgetstartdate","filter":{"items":[{"op":"=","value":"*past90days*","token":true}]}},{"fld":"widgetenddate"}] + +*/ \ No newline at end of file