Thursday, September 26, 2013

C#: Return each DateTime between @from and @to, stepped by a TimeSpan


        /// <summary>
        ///     Return each <see cref="DateTime" /> between <paramref name="from" /> and <paramref name="to" />, stepped by a
        ///     <see cref="TimeSpan" /> (<paramref name="step" />).
        /// </summary>
        /// <param name="from"></param>
        /// <param name="to"></param>
        /// <param name="step"></param>
        /// <returns></returns>
        /// <remarks>//TODO Untested code!</remarks>
        /// <example>
        ///     var now = DateTime.UtcNow;
        ///     var then = now.AddMinutes( 10 );
        ///     var minutes = now.To( then, TimeSpan.FromMinutes( 1 ) );
        ///     foreach ( var dateTime in minutes ) { Console.WriteLine( dateTime ); }
        /// </example>
        public static IEnumerable<DateTime> To( this DateTime from, DateTime to, TimeSpan? step = null ) {
            if ( !step.HasValue ) {
                try {
                    var diff = @from <= to ? to.Subtract( @from ) : @from.Subtract( @from );
 
                    if ( diff.TotalDays > 0 ) {
                        step = TimeSpan.FromDays( 1 );
                    }
                    else if ( diff.TotalHours > 0 ) {
                        step = TimeSpan.FromHours( 1 );
                    }
                    else if ( diff.TotalMinutes > 0 ) {
                        step = TimeSpan.FromMinutes( 1 );
                    }
                    else if ( diff.TotalSeconds > 0 ) {
                        step = TimeSpan.FromSeconds( 1 );
                    }
                    else {
                        step = TimeSpan.FromMilliseconds( 1 );
                    }
                }
                catch ( ArgumentOutOfRangeException ) {
                    step = TimeSpan.MaxValue;
                }
            }
 
            if ( from <= to ) {
                for ( var dt = from; dt <= to; dt += step.Value ) {
                    yield return dt;
                }
            }
            else {
                for ( var dt = from; dt >= to; dt -= step.Value ) {
                    yield return dt;
                }
            }
        }

No comments: