/// <summary>
        /// The create.
        /// </summary>
        /// <param name="timeFormat">
        /// The time format.
        /// </param>
        /// <returns>
        /// The <see cref="IPeriodicity"/>.
        /// </returns>
        /// <exception cref="ArgumentOutOfRangeException">Throws ArgumentOutOfRangeException
        /// </exception>
        public static IPeriodicity Create(TimeFormatEnumType timeFormat)
        {
            IPeriodicity value;
            if (_periodicities.TryGetValue(timeFormat, out value))
            {
                return value;
            }

            throw new ArgumentOutOfRangeException("timeFormat", timeFormat, "Not supported periodicity.");
        }
        /// <summary>
        /// Initializes a new instance of the <see cref="SdmxDateCore"/> class.
        /// </summary>
        /// <param name="date">
        /// The sdmxDate. 
        /// </param>
        /// <param name="timeFormat">
        /// The time format. 
        /// </param>
        /// ///
        /// <exception cref="ArgumentNullException">
        /// Throws ArgumentNullException.
        /// </exception>
        public SdmxDateCore(DateTime? date, TimeFormatEnumType timeFormat)
        {
            if (date == null)
            {
                throw new ArgumentNullException("date");
            }

            this._date = date.Value;
            this._timeFormat = TimeFormat.GetFromEnum(timeFormat);
            this._dateInSdmx = DateUtil.FormatDate(date.Value, timeFormat);
        }
        /// <summary>
        /// Parse a time where condition
        /// </summary>
        /// <param name="DateFrom">Date From in Sdmx Format</param>
        /// <param name="DateTo">Date To in Sdmx Format</param>
        /// <returns>string representing the date where formatted</returns>
        private string ParseTimeValueWhereStatment(ISdmxDate DateFrom, ISdmxDate DateTo)
        {
            try
            {
                IConceptObjectImpl realConceptTime = Concepts.Find(c => c.ConceptType == ConceptTypeEnum.Dimension && ((IDimensionConcept)c).DimensionType == DimensionTypeEnum.Time);
                string             timedim         = string.Format(FormatWhereValue, ((IDimensionConcept)realConceptTime).GetColumTimeName());
                List <string>      SingleValues    = new List <string>();

                //dò per scontato che i timeFormat delle 2 date siano Uguali
                TimeFormatEnumType tf = TimeFormatEnumType.Null;
                if (DateFrom != null && DateFrom.Date.HasValue)
                {
                    tf = DateFrom.TimeFormatOfDate.EnumType;
                    string wherestr = TimePeriodDBFormat.GetTimeWhereStatment(timedim, TimePeriodDBFormat.TypeDateOperation.Major, tf, DateFrom);
                    if (!string.IsNullOrEmpty(wherestr))
                    {
                        SingleValues.Add(wherestr);
                    }
                }

                if (DateTo != null && DateTo.Date.HasValue)
                {
                    if (tf == TimeFormatEnumType.Null)
                    {
                        tf = DateTo.TimeFormatOfDate.EnumType;
                    }
                    string wherestr = TimePeriodDBFormat.GetTimeWhereStatment(timedim, FlyController.Model.TimePeriodDBFormat.TypeDateOperation.Minor, tf, DateTo);
                    if (!string.IsNullOrEmpty(wherestr))
                    {
                        SingleValues.Add(wherestr);
                    }
                }

                if (SingleValues.Count > 0)
                {
                    return(string.Format("({0})", string.Join(") AND (", SingleValues)));
                }

                return(null);
            }
            catch (SdmxException) { throw; }
            catch (Exception ex)
            {
                throw new SdmxException(this, FlyExceptionObject.FlyExceptionTypeEnum.InternalError, ex);
            }
        }
        /// <summary>
        /// The iterate date values.
        /// </summary>
        /// <param name="dateFrom">
        /// The date from.
        /// </param>
        /// <param name="dateTo">
        /// The date to.
        /// </param>
        /// <param name="returnList">
        /// The return list.
        /// </param>
        /// <param name="format">
        /// The format.
        /// </param>
        private static void IterateDateValues(
            DateTime dateFrom, DateTime dateTo, ICollection<string> returnList, TimeFormatEnumType format)
        {
            IPeriodicity periodicity = PeriodicityFactory.Create(format);

            DateTime pointer = dateFrom;
            while ((pointer.Ticks / 10000) <= (dateTo.Ticks / 10000))
            {
                returnList.Add(FormatDate(pointer, format));
                pointer = periodicity.AddPeriod(pointer);
            }
        }
        /// <summary>
        /// Return an SDMX-ML formatted time period, based on the frequency supplied. The value
        ///  returned from this method will be determined based on the frequency and the date value
        ///  supplied as follows:
        ///  Annual: The year of the date
        ///  Biannual: January 1 - June 30 = 1st half, July 1 - December 31 = 2nd half
        ///  Triannual: January 1 - April 30 = 1st third, May 1 - August 30 = 2nd third, September 1 - December 31 = 3rd third
        ///  Quarterly: January 1 - March 31 = 1st quarter, April 1 - June 30 = 2nd quarter, July 1 - September 30 = 3rd quarter, October 1 - December 31 = 4th quarter
        ///  Mothly: The month of the date
        ///  Weekly: The week of the year according to ISO 8601.
        ///  Daily: The date only
        ///  Hourly: The full date time representation.
        /// </summary>
        /// <param name="date">
        /// the date to convert 
        /// </param>
        /// <param name="format">
        /// The format.
        /// </param>
        /// <returns>
        /// The date in SDMX-ML <c>TimePeriodType</c> format. 
        /// </returns>
        public static string FormatDate(DateTime date, TimeFormatEnumType format)
        {
            ////string df = null;
            ////string formatted = null;
            ////Calendar cal;
            IPeriodicity periodicity = PeriodicityFactory.Create(format);
            return periodicity.ToString(date);

            ////switch (format) {
            ////  case Org.Sdmxsource.Sdmx.Api.Constants.TimeFormatEnumType.Date:
            ////  df = DateFormat;
            ////      return date.ToString(df, CultureInfo.InvariantCulture);

            ////  case Org.Sdmxsource.Sdmx.Api.Constants.TimeFormatEnumType.DateTime:
            ////  df = DateTimeFormat;
            ////  return date.ToString(df, CultureInfo.InvariantCulture);

            ////  case Org.Sdmxsource.Sdmx.Api.Constants.TimeFormatEnumType.Year:
            ////  df = YearFormat;
            ////  return date.ToString(df, CultureInfo.InvariantCulture);
            ////      // what is the point here ?
            ////  ////formatted = df.Format(date);
            ////  ////cal = ILOG.J2CsMapping.Util.Calendar.GetInstance();
            ////  ////cal.SetTime(date);
            ////  ////return formatted;

            ////  case Org.Sdmxsource.Sdmx.Api.Constants.TimeFormatEnumType.HalfOfYear:

            ////  df = YearFormat;
            ////  formatted = df.Format(date);
            ////  cal = ILOG.J2CsMapping.Util.Calendar.GetInstance();
            ////  cal.SetTime(date);
            ////  if (cal.Get(ILOG.J2CsMapping.Util.Calendar.MONTH) <= 6) {
            ////      formatted += "-B1";
            ////  } else {
            ////      formatted += "-B2";
            ////  }
            ////  return formatted;

            ////  case Org.Sdmxsource.Sdmx.Api.Constants.TimeFormatEnumType.HOUR:
            ////  df = DateTimeFormat;
            ////  return df.Format(date);

            ////  case Org.Sdmxsource.Sdmx.Api.Constants.TimeFormatEnumType.MONTH:
            ////  df = MonthFormat;
            ////  return df.Format(date);

            ////  case Org.Sdmxsource.Sdmx.Api.Constants.TimeFormatEnumType.QUARTER_OF_YEAR:
            ////  df = YearFormat;
            ////  formatted = df.Format(date);
            ////  cal = ILOG.J2CsMapping.Util.Calendar.GetInstance();
            ////  cal.SetTime(date);
            ////  if (cal.Get(ILOG.J2CsMapping.Util.Calendar.MONTH) <= 2) {
            ////      formatted += "-Q1";
            ////  } else if (cal.Get(ILOG.J2CsMapping.Util.Calendar.MONTH) <= 5) {
            ////      formatted += "-Q2";
            ////  } else if (cal.Get(ILOG.J2CsMapping.Util.Calendar.MONTH) <= 8) {
            ////      formatted += "-Q3";
            ////  } else {
            ////      formatted += "-Q4";
            ////  }
            ////  return formatted;

            ////  case Org.Sdmxsource.Sdmx.Api.Constants.TimeFormatEnumType.THIRD_OF_YEAR:
            ////  df = YearFormat;
            ////  formatted = df.Format(date);
            ////  cal = ILOG.J2CsMapping.Util.Calendar.GetInstance();
            ////  cal.SetTime(date);
            ////  if (cal.Get(ILOG.J2CsMapping.Util.Calendar.MONTH) <= 3) {
            ////      formatted += "-T1";
            ////  } else if (cal.Get(ILOG.J2CsMapping.Util.Calendar.MONTH) <= 7) {
            ////      formatted += "-T2";
            ////  } else {
            ////      formatted += "-T3";
            ////  }
            ////  return formatted;

            ////  case Org.Sdmxsource.Sdmx.Api.Constants.TimeFormatEnumType.WEEK:
            ////  cal = ILOG.J2CsMapping.Util.Calendar.GetInstance();
            ////  cal.SetTime(date);
            ////  int weekNum = cal.Get(ILOG.J2CsMapping.Util.Calendar.WEEK_OF_YEAR);
            ////  int year = cal.Get(ILOG.J2CsMapping.Util.Calendar.YEAR);
            ////  int month = cal.Get(ILOG.J2CsMapping.Util.Calendar.MONTH);

            ////  //Due to a problem with the Java Calendar the year is wrong when parsing a date which corresponds to the 53rd week in a 53 week year
            ////  //Such as 2004-53, if the week is the 53rd but the month is Jan, then deduct one from the year to fix the problem
            ////  if (weekNum == 53 && month == 0) {
            ////      year--;
            ////  }
            ////  formatted = year + "-W" + weekNum;

            ////  return formatted;
            ////}
            ////return null;
        }
 /// <summary>
 /// Initializes a new instance of the <see cref="BasePeriodicity"/> class.
 /// </summary>
 /// <param name="timeFormat">
 /// The time format. 
 /// </param>
 protected BasePeriodicity(TimeFormatEnumType timeFormat)
 {
     this._timeFormat = TimeFormat.GetFromEnum(timeFormat);
 }
        /// <summary>
        /// Create a Where Condition filtering Time from Time period value
        /// </summary>
        /// <param name="timedim">Time period colum name</param>
        /// <param name="to">Date to (TypeDateOperation)</param>
        /// <param name="tf">Time format type</param>
        /// <param name="dt">Date in Sdmx Format</param>
        /// <returns></returns>
        public static string GetTimeWhereStatment(string timedim, TypeDateOperation to, TimeFormatEnumType tf, ISdmxDate dt)
        {
            try
            {
                string        SymbolComp        = to == TypeDateOperation.Minor ? "<" : ">";
                List <string> OrTimeFormatWhere = new List <string>();

                int MounthConsidered = dt.Date.Value.Month;
                if (tf == TimeFormatEnumType.Year && to == TypeDateOperation.Minor)
                {
                    MounthConsidered = 12;
                }

                //Tutte le possibili condizioni
                //==yyyy-MM-dd oppure yyyyMMdd
                OrTimeFormatWhere.Add(string.Format("({0} = '{2}')", timedim, SymbolComp, dt.Date.Value.ToString("yyyy-MM-dd")));
                OrTimeFormatWhere.Add(string.Format("({0} = '{2}')", timedim, SymbolComp, dt.Date.Value.ToString("yyyyMMdd")));
                #region Anno
                OrTimeFormatWhere.Add(string.Format("(DATALENGTH({0}) = 4 AND {0} {1}= '{2}')", timedim, SymbolComp, dt.Date.Value.Year));
                #endregion
                #region Mensile
                string DBtimecode = MappingTimePeriodDbFormat[TimeFormat.GetFromEnum(TimeFormatEnumType.Month)];
                OrTimeFormatWhere.Add(string.Format(@"
(
    DATALENGTH({0}) > 4 AND
    SUBSTRING({0},5,1) ='{1}' 
    AND 
    (
        SUBSTRING({0},0,5) {2} '{3}' 
        OR
        (
            SUBSTRING({0},0,5) = '{3}' 
            AND 
            CONVERT(int,SUBSTRING({0},6,DATALENGTH({0})-5)) {2}= {4}
        )
    )
)", timedim, DBtimecode, SymbolComp, dt.Date.Value.Year, MounthConsidered));
                #endregion
                #region Quartely
                DBtimecode = MappingTimePeriodDbFormat[TimeFormat.GetFromEnum(TimeFormatEnumType.QuarterOfYear)];
                int quarter = (MounthConsidered + 2) / 3;
                OrTimeFormatWhere.Add(string.Format(@"
(
    DATALENGTH({0}) > 4 AND
    SUBSTRING({0},5,1) ='{1}' 
    AND 
    (
        SUBSTRING({0},0,5) {2} '{3}' 
        OR
        (
            SUBSTRING({0},0,5) = '{3}' 
            AND 
            CONVERT(int,SUBSTRING({0},6,DATALENGTH({0})-5)) {2}= {4}
        )
    )
)", timedim, DBtimecode, SymbolComp, dt.Date.Value.Year, quarter));
                #endregion
                #region ThirdOfYear
                DBtimecode = MappingTimePeriodDbFormat[TimeFormat.GetFromEnum(TimeFormatEnumType.ThirdOfYear)];
                int ThirdOfYear = (MounthConsidered + 3) / 4;
                OrTimeFormatWhere.Add(string.Format(@"
(
    DATALENGTH({0}) > 4 AND
    SUBSTRING({0},5,1) ='{1}' 
    AND 
    (
        SUBSTRING({0},0,5) {2} '{3}' 
        OR
        (
            SUBSTRING({0},0,5) = '{3}' 
            AND 
            CONVERT(int,SUBSTRING({0},6,DATALENGTH({0})-5)) {2}= {4}
        )
    )
)", timedim, DBtimecode, SymbolComp, dt.Date.Value.Year, ThirdOfYear));
                #endregion
                #region HalfOfYear
                DBtimecode = MappingTimePeriodDbFormat[TimeFormat.GetFromEnum(TimeFormatEnumType.HalfOfYear)];
                int HalfOfYear = (MounthConsidered + 5) / 6;
                OrTimeFormatWhere.Add(string.Format(@"
(
    DATALENGTH({0}) > 4 AND
    SUBSTRING({0},5,1) ='{1}' 
    AND 
    (
        SUBSTRING({0},0,5) {2} '{3}' 
        OR
        (
            SUBSTRING({0},0,5) = '{3}' 
            AND 
            CONVERT(int,SUBSTRING({0},6,DATALENGTH({0})-5)) {2}= {4}
        )
    )
)", timedim, DBtimecode, SymbolComp, dt.Date.Value.Year, HalfOfYear));
                #endregion


                return(string.Format("({0})", string.Join(" OR ", OrTimeFormatWhere)));

                //                if (tf == TimeFormatEnumType.Year)
                //                {
                //                    return string.Format("(DATALENGTH({0}) = 4 AND {0} {1} '{2}')", timedim, SymbolComp, dt.Date.Value.Year);
                //                }
                //                else
                //                {
                //                    string queryValAfterFreq = dt.Date.Value.Month.ToString();
                //                    if (dt.DateInSdmxFormat.IndexOf(dt.TimeFormatOfDate.FrequencyCode) > 4)
                //                        queryValAfterFreq = dt.DateInSdmxFormat.Substring(dt.DateInSdmxFormat.IndexOf(dt.TimeFormatOfDate.FrequencyCode) + 1);

                //                    string DBtimecode = dt.TimeFormatOfDate.FrequencyCode;
                //                    //Trasformo il codice SDMX freq nel nostro formato time nel DB
                //                    if (MappingTimePeriodDbFormat.ContainsKey(dt.TimeFormatOfDate)) //nel Mapping devono essere presenti tutti i timeformat
                //                        DBtimecode = MappingTimePeriodDbFormat[dt.TimeFormatOfDate];

                //                    return string.Format(@"
                //(
                //    SUBSTRING({0},5,1) ='{1}'
                //    AND
                //    (
                //        SUBSTRING({0},0,5) {2} '{3}'
                //        OR
                //        (
                //            SUBSTRING({0},0,5) = '{3}'
                //            AND
                //            CONVERT(int,SUBSTRING({0},6,DATALENGTH({0})-5)) {2}= {4}
                //        )
                //    )
                //)",
                //                    timedim, DBtimecode, SymbolComp, dt.Date.Value.Year, queryValAfterFreq);
                //                }
            }
            catch (SdmxException) { throw; }
            catch (Exception ex)
            {
                throw new SdmxException(typeof(FlyController.Model.TimePeriodDBFormat), FlyExceptionObject.FlyExceptionTypeEnum.InternalError, ex);
            }
        }
 public void TestGetTimeFormatOfDate(string dateStr, TimeFormatEnumType timeFormat)
 {
     var timeFormatOfDate = DateUtil.GetTimeFormatOfDate(dateStr);
     Assert.NotNull(timeFormatOfDate);
     Assert.AreEqual(timeFormat, timeFormatOfDate.EnumType);
 }