Tarun Arora
Tarun Arora

Reputation: 4822

Use linq to get date difference in list items

I have a list of appointments, I would like to do a difference between the current appointment start time and last appointment end time to ensure there is no difference. If there is add a fake appointment.

My current implementation is...

public ObservableCollection<Appointment> FillGaps()
        {
            var appointments = this.Appointments.OrderByDescending(s => s.EndDate).ToList();

            for (int i = 0; i < appointments.Count() - 1; i++)
            {
                var now = appointments[i];

                var previous = appointments[i + 1];

                if((now.StartDate.Value - previous.EndDate.Value).Days > 1)
                {
                    // add a new appointment between this period
                    appointments.Add(new Appointment() 
                          { 
                             StartDate = previous.EndDate.Value.AddDays(1),
                             EndDate = now.StartDate.Value.AddDays(-1), 
                             IsCurrent = false 
                           });
                }
            }

            return appointments.ToObservableCollection();
        }

Is there a better or more generic way to do this?

As requested... Adding implementation of ToObservable...

 /// <summary>
        /// The to observable collection.
        /// </summary>
        /// <param name="coll">
        /// The collection.
        /// </param>
        /// <typeparam name="T"> Object T
        /// </typeparam>
        /// <returns>
        /// The <see cref="ObservableCollection"/>.
        /// </returns>
        public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> coll)
        {
            var c = new ObservableCollection<T>();
            foreach (var e in coll)
            {
                c.Add(e);
            }

            return c;
        }

Nothing special in Appointment class.

/// <summary>
    /// The Appointment.
    /// </summary>
    [Serializable]
    public class Appointment
    {
        public Appointment()
        {
            this.IsFake = false;
        }


        /// <summary>
        /// Gets or sets the start date.
        /// </summary>
        public DateTime? StartDate { get; set; }

        /// <summary>
        /// Gets or sets the end date.
        /// </summary>
        public DateTime? EndDate { get; set; }

        /// <summary>
        /// Gets or sets the Is Fake
        /// </summary>
        public bool IsFake { get; set; }

    }

Upvotes: 2

Views: 659

Answers (1)

Richard Deeming
Richard Deeming

Reputation: 31208

Without knowing how the this.Appointments property is implemented, or what the parameter to the ToObservableCollection extension method is, it's difficult to come up with the most effective solution. However, something like this should work:

private static IEnumerable<Tuple<T, T>> ListPairs<T>(IEnumerable<T> source)
{
   using (var enumerator = source.GetEnumerator())
   {
       if (!enumerator.MoveNext()) yield break;

       T previous = enumerator.Current;
       while (enumerator.MoveNext())
       {
          T current = enumerator.Current;
          yield return new Tuple<T, T>(previous, current);
          previous = current;
       }
   }
}

public ObservableCollection<Appointment> FillGaps()
{
   var gaps = ListPairs(this.Appointments.OrderByDescending(s => s.EndDate))
      .Where(pair => (pair.Item1.StartDate.Value - pair.Item2.EndDate.Value).Days > 1)
      .Select(pair => new Appointment
      {
         StartDate = pair.Item2.EndDate.Value.AddDays(1),
         EndDate = pair.Item1.StartDate.Value.AddDays(-1),
         IsCurrent = false,
      });

   // NB: Assumes "this.Appointments" is a cheap call;
   // Also assumes you don't need the results in any particular order.
   return this.Appointments.Concat(gaps).ToObservableCollection();
}

Upvotes: 1

Related Questions