/*
**************************************************************
* AjaxCalendarToolkit
**************************************************************
* Author: Rohit Gadagkar (rohit.gadagkar@gmail.com)
* Copyright � 2007 Rohit Gadagkar
* License:
* Free without any restrictions whatsoever
*
* Created: 7/10/2007
*
* THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY
* OF ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT
* LIMITED TO THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE.
**************************************************************
*/
using System;
using System.Collections.Generic;
using System.Text;
using AjaxCalendarToolkit.Properties;
namespace AjaxCalendarToolkit.UI
{
internal class DateExpressionBuilder
{
static readonly string[] daysOfWeek1Letter;
static readonly string[] daysOfWeek3Letter;
static readonly string[] dateSuffixes;
private DateDisplaySpec _dateDisplaySpec;
private DateDisplayOrder _dateDisplayOrder;
private string _yearPrefix;
private string _yearSuffix;
private string _monthPrefix;
private string _monthSuffix;
private string _datePrefix;
private string _dateSuffix;
private string _dayOfWeekPrefix;
private string _dayOfWeekSuffix;
private bool _overridePrefixSuffixBehaviourUsingDefault;
static class Defaults
{
internal const string YearPrefix = " ";
internal const string YearSuffix = " ";
internal const string MonthSuffix = " ";
internal const string MonthPrefix = " ";
internal const string DateSuffix = " ";
internal const string DatePrefix = " ";
internal const string DayOfWeekSuffix = ", ";
internal const string DayOfWeekPrefix = " ";
internal const string NumericSeperator = "/";
internal const string WordSeperator = " ";
}
/// <summary>
/// Defines the prefix, suffix behaviour of DateExpressionBuilder.
/// If set to true, the user need not specify prefix and suffix strings for the date
/// components. Default values will be used if required, depending on the bits
/// specified in the DateDisplaySpec.
/// </summary>
/// <remarks>
/// This property is true by default. If DateDisplaySpecs for all date component(s)
/// are numeric, the default delimiter is "/". If not, the default delimiter is a
/// whitespace. This class does a sanity check before applying prefix and suffix strings.
///
/// Note -
/// If user has specified one of the prefix or suffix properties (example DateSuffix)
/// and OverridePrefixSuffixBehaviourUsingDefault is true (the default), the user
/// specified prefix and suffixes will not be used. The default behaviour will be used
/// instead.
/// </remarks>
public bool OverridePrefixSuffixBehaviourUsingDefault
{
get { return _overridePrefixSuffixBehaviourUsingDefault; }
set { _overridePrefixSuffixBehaviourUsingDefault = value; }
}
string GetPropertyValue(bool isPropertyEmpty, string propertyValue)
{
return isPropertyEmpty? String.Empty : propertyValue;
}
bool IsPropertyValueEmpty(
DateDisplaySpec propertyFlag,
DateDisplaySpec[] validFlags)
{
DoSmartFormat();
bool res1 = (_dateDisplaySpec & propertyFlag) != 0;
if (res1)
{
bool res2 = false;
foreach (DateDisplaySpec flag in validFlags)
res2 |= ((_dateDisplaySpec & flag) != 0);
return !res2;
}
return true;
}
public string DayOfWeekSuffix
{
get {
return GetPropertyValue(
IsPropertyValueEmpty(
DateDisplaySpec.DayOfWeekSuffix,
new DateDisplaySpec[] {
DateDisplaySpec.DayOfWeekFullWord,
DateDisplaySpec.DayOfWeek3LetterAbbreviation,
DateDisplaySpec.DayOfWeekNumeric}),
_dayOfWeekSuffix);
}
set { _dayOfWeekSuffix = value;
SetDateFlagOnOff(value, DateDisplaySpec.DayOfWeekSuffix);
}
}
public string DayOfWeekPrefix
{
get {
return GetPropertyValue(
IsPropertyValueEmpty(
DateDisplaySpec.DayOfWeekPrefix,
new DateDisplaySpec[] {
DateDisplaySpec.DayOfWeekFullWord,
DateDisplaySpec.DayOfWeek3LetterAbbreviation,
DateDisplaySpec.DayOfWeekNumeric}),
_dayOfWeekPrefix);
}
set { _dayOfWeekPrefix = value;
SetDateFlagOnOff(value, DateDisplaySpec.DayOfWeekPrefix);
}
}
public string DateSuffix
{
get {
return GetPropertyValue(
IsPropertyValueEmpty(
DateDisplaySpec.DateSuffix|DateDisplaySpec.DateSuffix2Letter,
new DateDisplaySpec[] {
DateDisplaySpec.Date2Digit,
DateDisplaySpec.DateAnyDigits}),
_dateSuffix);
}
set { _dateSuffix = value;
SetDateFlagOnOff(value, DateDisplaySpec.DateSuffix);
}
}
public bool AutoGenerateTwoLetterDateSuffix
{
get {
return ((_dateDisplaySpec & DateDisplaySpec.DateSuffix2Letter) != 0);
}
set {
SetDateFlagOnOff(value, DateDisplaySpec.DateSuffix2Letter);
}
}
public string DatePrefix
{
get {
return GetPropertyValue(
IsPropertyValueEmpty(
DateDisplaySpec.DatePrefix,
new DateDisplaySpec[] {
DateDisplaySpec.Date2Digit,
DateDisplaySpec.DateAnyDigits}),
_datePrefix);
}
set { _datePrefix = value;
SetDateFlagOnOff(value, DateDisplaySpec.DatePrefix);
}
}
public string MonthSuffix
{
get {
return GetPropertyValue(
IsPropertyValueEmpty(
DateDisplaySpec.MonthSuffix,
new DateDisplaySpec[] {
DateDisplaySpec.Month3LetterAbbreviation,
DateDisplaySpec.MonthFullWord,
DateDisplaySpec.MonthNumeric2Digits,
DateDisplaySpec.MonthNumericAnyDigits}),
_monthSuffix);
}
set { _monthSuffix = value;
SetDateFlagOnOff(value, DateDisplaySpec.MonthSuffix);
}
}
public string MonthPrefix
{
get {
return GetPropertyValue(
IsPropertyValueEmpty(
DateDisplaySpec.MonthPrefix,
new DateDisplaySpec[] {
DateDisplaySpec.Month3LetterAbbreviation,
DateDisplaySpec.MonthFullWord,
DateDisplaySpec.MonthNumeric2Digits,
DateDisplaySpec.MonthNumericAnyDigits}),
_monthPrefix);
}
set { _monthPrefix = value;
SetDateFlagOnOff(value, DateDisplaySpec.MonthPrefix);
}
}
public string YearSuffix
{
get {
return GetPropertyValue(
IsPropertyValueEmpty(
DateDisplaySpec.YearSuffix,
new DateDisplaySpec[] {
DateDisplaySpec.Year2Digits,
DateDisplaySpec.Year4Digits}),
_yearSuffix);
}
set { _yearSuffix = value;
SetDateFlagOnOff(value, DateDisplaySpec.YearSuffix);
}
}
public string YearPrefix
{
get {
return GetPropertyValue(
IsPropertyValueEmpty(
DateDisplaySpec.YearPrefix,
new DateDisplaySpec[] {
DateDisplaySpec.Year2Digits,
DateDisplaySpec.Year4Digits}),
_yearPrefix);
}
set { _yearPrefix = value;
SetDateFlagOnOff(value, DateDisplaySpec.YearPrefix);
}
}
public DateDisplayOrder DateDisplayOrder
{
get { return _dateDisplayOrder; }
set { _dateDisplayOrder = value; DoSmartFormat(); }
}
public DateDisplaySpec DateDisplaySpec
{
get { return _dateDisplaySpec; }
set { _dateDisplaySpec = value; DoSmartFormat(); }
}
static DateExpressionBuilder()
{
daysOfWeek1Letter = Resources.DaysOfWeek1Letter.Split(
new string[] { Resources.ArrayDelimiter }, StringSplitOptions.None);
daysOfWeek3Letter = Resources.DaysOfWeek3Letter.Split(
new string[] { Resources.ArrayDelimiter }, StringSplitOptions.None);
dateSuffixes = Resources.DateSuffixes.Split(
new string[] { Resources.ArrayDelimiter }, StringSplitOptions.None);
}
public DateExpressionBuilder(DateDisplaySpec specs, DateDisplayOrder displayOrder,
bool overridePrefixSuffixBehaviourUsingDefault)
{
_dateDisplaySpec = specs; _dateDisplayOrder = displayOrder;
_overridePrefixSuffixBehaviourUsingDefault = overridePrefixSuffixBehaviourUsingDefault;
}
public DateExpressionBuilder(DateDisplaySpec specs, DateDisplayOrder displayOrder)
: this(specs, displayOrder, true)
{}
public DateExpressionBuilder(DateDisplaySpec specs)
: this(specs, DateDisplayOrder.DayOfWeek_Month_Date_Year)
{ }
public DateExpressionBuilder()
: this(
DateDisplaySpec.Year4Digits | DateDisplaySpec.MonthFullWord |
DateDisplaySpec.DateAnyDigits | DateDisplaySpec.DayOfWeekFullWord |
DateDisplaySpec.DayOfWeekSuffix | DateDisplaySpec.MonthSuffix |
DateDisplaySpec.DateSuffix | DateDisplaySpec.DateSuffix2Letter)
{}
public string FormatDate(DateTime date)
{
DoSmartFormat();
return date.ToString(ConstructFullFormatString(date));
}
internal bool DayOfWeekBitIsSet
{
get {
return (_dateDisplaySpec & DateDisplaySpec.DayOfWeek3LetterAbbreviation) != 0
|| (_dateDisplaySpec & DateDisplaySpec.DayOfWeekFullWord) != 0
|| (_dateDisplaySpec & DateDisplaySpec.DayOfWeekNumeric) != 0;
}
}
internal bool MonthBitIsSet
{
get {
return (_dateDisplaySpec & DateDisplaySpec.Month3LetterAbbreviation) != 0
|| (_dateDisplaySpec & DateDisplaySpec.MonthFullWord) != 0
|| (_dateDisplaySpec & DateDisplaySpec.MonthNumeric2Digits) != 0
|| (_dateDisplaySpec & DateDisplaySpec.MonthNumericAnyDigits) != 0;
}
}
internal bool DateBitIsSet
{
get {
return (_dateDisplaySpec & DateDisplaySpec.Date2Digit) != 0
|| (_dateDisplaySpec & DateDisplaySpec.DateAnyDigits) != 0;
}
}
internal bool YearBitIsSet
{
get {
return (_dateDisplaySpec & DateDisplaySpec.Year2Digits) != 0
|| (_dateDisplaySpec & DateDisplaySpec.Year4Digits) != 0;
}
}
internal bool AllNumericBits
{
get {
bool dow = ((DayOfWeekBitIsSet &&
(_dateDisplaySpec & DateDisplaySpec.DayOfWeekNumeric)!=0))
|| (!DayOfWeekBitIsSet);
bool m = (MonthBitIsSet &&
((_dateDisplaySpec & DateDisplaySpec.MonthNumeric2Digits) != 0
|| (_dateDisplaySpec & DateDisplaySpec.MonthNumericAnyDigits) != 0))
|| !MonthBitIsSet;
bool dt = DateBitIsSet;
bool yr = YearBitIsSet;
return dow && m && dt && yr;
}
}
internal void SetDateFlagOnOff(string stringPropertyValue, DateDisplaySpec dateFlag)
{
SetDateFlag(String.IsNullOrEmpty(stringPropertyValue), dateFlag);
}
internal void SetDateFlagOnOff(bool boolPropertyValue, DateDisplaySpec dateFlag)
{
SetDateFlag(boolPropertyValue, dateFlag);
}
internal void SetDateFlag(bool turnOffFlagBit, DateDisplaySpec dateFlag)
{
if (turnOffFlagBit && (_dateDisplaySpec & dateFlag) != 0)
_dateDisplaySpec ^= dateFlag;
else if (!turnOffFlagBit) _dateDisplaySpec |= dateFlag;
}
/// <summary>
/// This method verifies and sets up valid values for default behaviour
/// Default prefix suffix behaviour is to
/// 1) put " " character as suffix (seperator)
/// 2) put "/" character as suffix when all date component specs are numeric
/// 3) default behaviour suffixes override any user supplied values through the
/// prefix and suffix date component properties.
/// If UseDefaultPrefixSuffixBehaviour is set to false, the user is expected to
/// provide each of the date spec suffixes, which will be used as seperators in the
/// output.
/// </summary>
internal void DoSmartFormat()
{
if (_overridePrefixSuffixBehaviourUsingDefault)
{
DayOfWeekPrefix = String.Empty; DatePrefix = String.Empty;
MonthPrefix = String.Empty; YearPrefix = String.Empty;
_dateDisplaySpec |= (DateDisplaySpec.DateSuffix | DateDisplaySpec.DateSuffix2Letter
|DateDisplaySpec.MonthSuffix);
if (AllNumericBits) {
if (DateBitIsSet) DateSuffix = Defaults.NumericSeperator;
if (MonthBitIsSet) MonthSuffix = Defaults.NumericSeperator;
}
switch (_dateDisplayOrder)
{
case DateDisplayOrder.DayOfWeek_Date_Month_Year:
case DateDisplayOrder.DayOfWeek_Month_Date_Year:
_dateDisplaySpec |= DateDisplaySpec.DayOfWeekSuffix;
DayOfWeekSuffix = DayOfWeekBitIsSet
? (AllNumericBits ? Defaults.NumericSeperator : Defaults.WordSeperator)
: String.Empty;
if (DayOfWeekBitIsSet && !MonthBitIsSet && !DateBitIsSet & !YearBitIsSet)
DayOfWeekSuffix = String.Empty;
MonthSuffix = MonthBitIsSet
? (AllNumericBits ? Defaults.NumericSeperator : Defaults.WordSeperator)
: String.Empty;
if (MonthBitIsSet && (
(_dateDisplayOrder == DateDisplayOrder.DayOfWeek_Month_Date_Year
&& !DateBitIsSet && !YearBitIsSet)
|| (_dateDisplayOrder == DateDisplayOrder.DayOfWeek_Date_Month_Year
&& !YearBitIsSet)))
MonthSuffix = String.Empty;
DateSuffix = DateBitIsSet
? (AllNumericBits ? Defaults.NumericSeperator : Defaults.WordSeperator)
: String.Empty;
if (DateBitIsSet && (
(_dateDisplayOrder == DateDisplayOrder.DayOfWeek_Month_Date_Year
&& !YearBitIsSet)
|| (_dateDisplayOrder == DateDisplayOrder.DayOfWeek_Date_Month_Year
&& !YearBitIsSet && !MonthBitIsSet)))
DateSuffix = String.Empty;
if (YearBitIsSet) {
YearSuffix = String.Empty;
if (_dateDisplayOrder == DateDisplayOrder.DayOfWeek_Month_Date_Year
&& DateBitIsSet)
YearPrefix = Defaults.WordSeperator;
}
if (MonthBitIsSet && DateBitIsSet &&
DateDisplayOrder == DateDisplayOrder.DayOfWeek_Date_Month_Year)
MonthPrefix = Defaults.WordSeperator;
break;
case DateDisplayOrder.Year_Month_Date_DayOfWeek:
_dateDisplaySpec |= DateDisplaySpec.YearSuffix;
YearSuffix = YearBitIsSet
? (AllNumericBits ? Defaults.NumericSeperator : Defaults.WordSeperator)
: String.Empty;
if (YearBitIsSet && !MonthBitIsSet && !DateBitIsSet & !DayOfWeekBitIsSet)
YearSuffix = String.Empty;
MonthSuffix = MonthBitIsSet
? (AllNumericBits ? Defaults.NumericSeperator : Defaults.WordSeperator)
: String.Empty;
if (MonthBitIsSet && !DateBitIsSet && !DayOfWeekBitIsSet)
MonthSuffix = String.Empty;
DateSuffix = DateBitIsSet
? (AllNumericBits ? Defaults.NumericSeperator : Defaults.WordSeperator)
: String.Empty;
if (DateBitIsSet && !DayOfWeekBitIsSet)
DateSuffix = String.Empty;
if (DayOfWeekBitIsSet) {
DayOfWeekSuffix = String.Empty;
if (DateBitIsSet) DayOfWeekPrefix = Defaults.WordSeperator;
}
break;
}
}
}
//todo: Construct methods will include prefix and suffix in return values
internal string ConstructDayOfWeekFormat(DateTime d)
{
if (!DayOfWeekBitIsSet) return String.Empty;
string format = "'{0}'{1}'{2}'", val = null;
if ((_dateDisplaySpec & DateDisplaySpec.DayOfWeek3LetterAbbreviation) != 0)
val = "ddd";
else if ((_dateDisplaySpec & DateDisplaySpec.DayOfWeekFullWord) != 0)
val = "dddd";
else if ((_dateDisplaySpec & DateDisplaySpec.DayOfWeekNumeric) != 0)
val = "%d";
return String.Format(format, DayOfWeekPrefix, val, DayOfWeekSuffix);
}
internal string ConstructMonthFormat(DateTime d)
{
if (!MonthBitIsSet) return String.Empty;
string format = "'{0}'{1}'{2}'", val = null;
if ((_dateDisplaySpec & DateDisplaySpec.Month3LetterAbbreviation) != 0)
val = "MMM";
else if ((_dateDisplaySpec & DateDisplaySpec.MonthFullWord) != 0)
val = "MMMM";
else if ((_dateDisplaySpec & DateDisplaySpec.MonthNumeric2Digits) != 0)
val = "MM";
else if ((_dateDisplaySpec & DateDisplaySpec.MonthNumericAnyDigits) != 0)
val = "%M";
return String.Format(format, MonthPrefix, val, MonthSuffix);
}
internal string ConstructDateFormat(DateTime d)
{
//todo: for the date suffix, if 2letter bit is there return dynamic suffix from resouces
if (!DateBitIsSet) return String.Empty;
string format = "'{0}'{1}'{2}'", val = null;
if ((_dateDisplaySpec & DateDisplaySpec.Date2Digit) != 0)
val = "dd";
else if ((_dateDisplaySpec & DateDisplaySpec.DateAnyDigits) != 0)
val = "%d";
return String.Format(format, DatePrefix, val,
AutoGenerateTwoLetterDateSuffix ? GetDateSuffix(d) : DateSuffix);
}
internal string ConstructYearFormat(DateTime d)
{
if (!YearBitIsSet) return String.Empty;
string format = "'{0}'{1}'{2}'", val = null;
if ((_dateDisplaySpec & DateDisplaySpec.Year2Digits) != 0)
val = "yy";
else if ((_dateDisplaySpec & DateDisplaySpec.Year4Digits) != 0)
val = "yyyy";
return String.Format(format, YearPrefix, val, YearSuffix);
}
internal string ConstructFullFormatString(DateTime d)
{
string format = "{0}{1}{2}{3}";
switch (_dateDisplayOrder)
{
case DateDisplayOrder.DayOfWeek_Date_Month_Year:
case DateDisplayOrder.DayOfWeek_Month_Date_Year:
format = String.Format(format,
ConstructDayOfWeekFormat(d),
_dateDisplayOrder == DateDisplayOrder.DayOfWeek_Date_Month_Year
? ConstructDateFormat(d) : ConstructMonthFormat(d),
_dateDisplayOrder == DateDisplayOrder.DayOfWeek_Date_Month_Year
? ConstructMonthFormat(d) : ConstructDateFormat(d),
ConstructYearFormat(d));
break;
case DateDisplayOrder.Year_Month_Date_DayOfWeek:
format = String.Format(format,
ConstructYearFormat(d),
ConstructMonthFormat(d),
ConstructDateFormat(d),
ConstructDayOfWeekFormat(d));
break;
}
return format;
}
string GetDateSuffix(DateTime d)
{
int unitDigit = d.Day % 10;
if (d.Day >= 11 && d.Day <= 13) unitDigit = 0;
return unitDigit < dateSuffixes.Length ? dateSuffixes[unitDigit] : String.Empty;
}
}
}