How to add three months from incoming API dates using C#? - c#

How do you calculate dates from the database by adding 3 months?
I created a LINQ query that only selects the column EndYearMonth from the database. I was trying to set up a variable in the parameters called EndYearMonth which is also placed in the DateTime object. I got the DateTime function code using this link https://www.tutorialspoint.com/datetime-addmonths-method-in-chash. The problem is that this tutorial doesn't show you how to add three months from the database because there is only one date that is hardcoded.
Here is my code below
[HttpGet]
public ActionResult GetFinance(int EndYearMonth )
{
var dates = _context.Finances
.Select(e => e.EndYearMonth
)
.ToList();
DateTime d1 = new DateTime(EndYearMonth);
DateTime Q1 = d1.AddMonths(3);
DateTime Q2 = d1.AddMonths(6);
DateTime Q3 = d1.AddMonths(9);
DateTime[] array = {Q1, Q2 , Q3};
return Ok(array);
}
When I click send to get the request the output is this
The expected outcome should be this
This is the original data coming from the database

Use this code :
[HttpGet]
public ActionResult GetFinance()
{
var dates = _context.Finances
.Select(e => e.EndYearMonth)
.ToList();
int arrayLength = dates.Count() * 4;
DateTime[] array = new DateTime[arrayLength];
int index = 0;
foreach (var strDate in dates)
{
DateTime d1 = DateTime.Parse(strDate);
DateTime Q1 = d1.AddMonths(3);
DateTime Q2 = d1.AddMonths(6);
DateTime Q3 = d1.AddMonths(9);
array[index] = d1;
array[index + 1] = Q1;
array[index + 2] = Q2;
array[index + 3] = Q3;
index += 4;
}
return Ok(array);
}

Just get EndOfYearDate from database as it is and then add 3 months to it. The code of adding 3 months is right but the line code below is wrong
DateTime d1 = new DateTime(EndYearMonth);
To resolve this simply get the datetime from database as it is and then add 3 months to it.

Related

How to find the postFix of a string

I have a list of filename in my folder and I convert the folder into a list. The file name is the same except for their postfix (number after the file name).
I want to get the latest postfix in that file list.
For example: In my list, I have 4 files. file_20160101 has the largest postfix. There for I want to get the name 'file_20160101' and add to my string.
[0] C:\\Desktop\\file_20130101.csv
[1] C:\\Desktop\\file_20140101.csv
[2] C:\\Desktop\\file_20150101.csv
[3] C:\\Desktop\\file_20160101.csv
Here is my code:
string fileDir = "C:\\Desktop\\"
List<string> list = new List<string>(Directory.GetFiles(fileDir));
string largestPrefix = //file_20160101.csv
You can get it like this:
List<string> list = new List<string>(Directory.GetFiles(fileDir));
var numericParts = Directory.GetFiles(fileDir).Select(f => int.Parse(Regex.Match(f, #"\d+").Value)).ToArray();
var max = numericParts.Max(); //do whatever you want with the largest number
You can even call the Max directly in the case you don't need other numeric parts:
var max = Directory.GetFiles(fileDir).Select(f => int.Parse(Regex.Match(f, #"\d+").Value)).ToArray().Max();
Considering you are looking for the most recent file.You can try this (but yeah linq solution is better.:))
string output = string.Empty;
DateTime max = new DateTime();
foreach(string str in list)
{
DateTime tempDate = new DateTime();
DateTime.TryParseExact(str.Substring(str.IndexOf("_") + 1, 8), "yyyyMMdd", CultureInfo.GetCultureInfo("en-Us"), DateTimeStyles.None , out tempDate);
if(tempDate > max)
{
max = tempDate;
output = str;
}
}
Below code can give you result very quickly if you know that prefix will be always like "file_"
list.Max(f => int.Parse(f.Replace("file_", string.Empty)))
You can do something like this
DateTime date = new DateTime();
string result = "";
foreach (var item in list)
{
int year = int.Parse(item.Substring(5 , 4));
int month = int.Parse(item.Substring(9, 2));
int day = int.Parse(item.Substring(11, 2));
DateTime currentDate = new DateTime(year, month, day);
if (currentDate > date)
{
date = currentDate;
result = item;
}
}
Console.WriteLine(result);

ASP.NET MVC Filter datetime by weeks

I've got a Web API and a Get method, returning a query:
var query = from results in context.Table
where results.Date>= startDate && results.Date <= endDate
select new
{
Week = { this is where I need a method to group by weeks },
Average = results.Where(x => x.Number).Average()
}
return query.ToList();
I want to calculate the average for each 7 days (that being the first week).
Example:
Average 1 ... day 7 (Week 1)
Average 2 ... day 14 (Week 2)
How can I do that? Being given an interval of datetimes, to filter it by weeks (not week of year)
Try this (not tested with tables)
var avgResult = context.QuestionaireResults
.Where(r => (r.DepartureDate >= startDate && r.DepartureDate <= endDate)).ToList()
.GroupBy( g => (Decimal.Round(g.DepartureDate.Day / 7)+1))
.Select( g => new
{
Week = g.Key,
Avg = g.Average(n => n.Number)
});
You will need to group by the number of days, since a reference date, divided by 7, so
.GroupBy(x => Math.Floor(((x.DepartureDate - new DateTime(1980,1,1)).TotalDays + 2) / 7))
Subtracting "Jan 1, 1980" from your departure date, gives you a TimeSpan object with the difference between the two dates. The TotalDays property of that timespan gives you timespan in days. Adding 2 corrects for the fact that "Jan 1, 1980" was a Tuesday. Dividing by 7 gives you the number of weeks since then. Math.Floor rounds it down, so that you get a consistent integer for the week, given any day of the week or portion of days within the week.
You could simplify a little by picking a reference date that is a Sunday (assuming that is your "first day of the week"), so you dont have to add 2 to correct. Like so:
.GroupBy(x => Math.Floor(((x.DepartureDate - new DateTime(1979,12,30)).TotalDays) / 7))
If you are sure that your data all falls within a single calendar year, you could maybe use the Calendar.GetWeekOfYear method to figure out the week, but I am not sure it would be any simpler.
Why not write a stored procedure, I think there may be some limitations on your flexibility using Linq because of the idea that normally the GroupBy groups by value (the value of the referenced "thing") so you can group by State, or Age, but I guess you can Group week... (new thought)
Add a property called EndOfWeek and for example, the end of this week is (Sunday let's say) then EndOfWeek = 9.2.16 whereas last week was 8.28.16... etc. then you can easily group but you still have to arrange the data.
I know I didn't answer the question but I hope that I sparked some brain activity in an area that allows you to solve the problem.
--------- UPDATED ----------------
simple solution, loop through your records, foreach record determine the EndOfWeek for that record. After this you will now have a groupable value. Easily group by EndOfWeek. Simple!!!!!!!!!!!! Now, #MikeMcCaughan please tell me how this doesn't work? Is it illogical to extend an object? What are you talking about?
------------ HERE IS THE CODE ----------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace SandboxConsole
{
class Program
{
static void Main(string[] args)
{
var t = new Transactions();
List<Transactions> transactions = t.GetTransactions();
// Now let's add a Weeks end date so we can determine the average per week
foreach(var transaction in transactions)
{
var transactionDayOfWeek = transaction.TransactionDate;
int daysUntilEndOfWeek_Sat = ((int)DayOfWeek.Saturday - (int)transactionDayOfWeek.DayOfWeek + 7) % 7;
transaction.Newly_Added_Property_To_Group_By_Week_To_Get_Averages = transactionDayOfWeek.AddDays(daysUntilEndOfWeek_Sat).ToShortDateString();
//Console.WriteLine("{0} {")
}
foreach(var weekEnd in transactions.GroupBy(tt => tt.Newly_Added_Property_To_Group_By_Week_To_Get_Averages))
{
decimal weekTotal = 0;
foreach(var trans in weekEnd)
{
weekTotal += trans.Amount;
}
var weekAverage = weekTotal / 7;
Console.WriteLine("Week End: {0} - Avg {1}", weekEnd.Key.ToString(), weekAverage.ToString("C"));
}
Console.ReadKey();
}
}
class Transactions
{
public int Id { get; set; }
public string SomeOtherProp { get; set; }
public DateTime TransactionDate { get; set; }
public decimal Amount { get; set; }
public string Newly_Added_Property_To_Group_By_Week_To_Get_Averages { get; set; }
public List<Transactions> GetTransactions()
{
var results = new List<Transactions>();
for(var i = 0; i<100; i++)
{
results.Add(new Transactions
{
Id = i,
SomeOtherProp = "Customer " + i.ToString(),
TransactionDate = GetRandomDate(i),
Amount = GetRandomAmount()
});
}
return results;
}
public DateTime GetRandomDate(int i)
{
Random gen = new Random();
DateTime startTime = new DateTime(2016, 1, 1);
int range = (DateTime.Today - startTime).Days + i;
return startTime.AddDays(gen.Next(range));
}
public int GetRandomAmount()
{
Random rnd = new Random();
int amount = rnd.Next(1000, 10000);
return amount;
}
}
}
------------ OUTPUT ---------------
Sample Output

How get list of datetimes from date range?

I have datetime range:
var _checkInYear = (from d in db.bookings select d.checkinyear).ToList();
var _checkInMonth = (from d in db.bookings select d.checkinmonth).ToList();
var _checkInDay = (from d in db.bookings select d.checkinday).ToList();
var _checkOutYear = (from d in db.bookings select d.checkoutyear).ToList();
var _checkOutMonth = (from d in db.bookings select d.checkoutmonth).ToList();
var _checkOutDay = (from d in db.bookings select d.checkoutday).ToList();
How can I get DateTime list from this range? For example if check in time is 20/08/2011 and check out 23/08/2011 need to put into list date time into this range.
20/08/2011, 21/08/2011, 22/08/2011, 23/08/2011.
DateTime checkIn = new DateTime(_checkInYear, _checkInMonth, _checkInDay);
DateTime checkOut = new DateTime(_checkOutYear, _checkOutMonth, _checkOutDay);
TimeSpan span = checkOut - checkIn;
List<DateTime> range = new List<DateTime>();
for(int day = 0; day <= span.Days; day++)
{
range.Add(checkIn.AddDays(day));
}
Example: http://www.ideone.com/BxmkF
The algorithm is simple, get your starting point, increment until you reach the ending point.
var startDate = new DateTime(checkInYear, checkInMonth, checkInDay);
var endDate = new DateTime(checkOutYear, checkOutMonth, checkOutDay);
var givenDate = startDate;
var datesInRange = new List<DateTime>();
while (givenDate <= startDate)
{
datesInRange.Add(givenDate);
givenDate = givenDate.AddDays(1);
}
// work with / return datesInRange
If you can get check-in and check-out date then you can have a extension method for DateTime to get list:
public static class ExtensionMethods
{
static IEnumerable<DateTime> GetDateRange(this DateTime d, DateTime e)
{
var t=d;
do
{
yield return t;
t=t.AddDays(1);
}while(t<e);
}
}
Then use it like this:
var dateList = checkIn.GetDateRange(checkOutDate);
Tested in Linqpad.
Given that you get your hands on two dates, your best bet is simply to use a for or while loop:
var dates = new List<DateTime>();
var curDate = booking.CheckinDate;
while (curDate <= booking.CheckoutDate)
{
dates.Add(curDate);
curDate = curDate.AddDays(1);
}
However, I appreciate this may be a contrived example for the purposes of the question, but I'm concerned your example code won't do what you want. Don't bother reading further if this is the case, I just wanted to highlight it on the off-chance that you might be better off with something like this:
var booking = (from b in data.Bookings
where b.BookingId = bookingId
select new BookingSearchResult // You have to create this class
{
CheckinDate = new DateTime(b.CheckinYear, b.CheckinMonth, b.CheckinDay),
CheckoutDate = new DateTime(b.CheckoutYear, b.CheckoutMonth, b.CheckoutDay)
}).SingleOrDefault();
A bit old question but i think we should do it lke that:
DateTime checkIn = new DateTime(_checkInYear, _checkInMonth, _checkInDay);
DateTime checkOut = new DateTime(_checkOutYear, _checkOutMonth, _checkOutDay);
List<DateTime> allDates = new List<DateTime> ();
for (DateTime date = checkIn; date <= checkOut; date = date.AddDays(1))
allDates.Add(date);

Find date ranges from a collection of dates C#

Simple question. I have an ordered collection of dates. They are UK dates btw
01/01/10
01/02/10
01/03/10
01/04/10
02/04/10
03/04/10
04/04/10
And I want to convert this into a collection of date ranges
01/01/10 -> 01/01/10
01/02/10 -> 01/02/10
01/03/10 -> 01/03/10
01/04/10 -> 04/04/10
Just to clarify, I'm trying to convert any consecutive dates into a range. so the first 3 dates are stand alone and the last 4 get converted into a range 1st of April to 4th of April.
Now I can do this using loops but it's not very elegant. Does any one have any solutions out there that are?
Thanks
Given that you want to determine ranges of consecutive date ranges, I think your only option is, as you say a loop. You can do it in a single pass though, and put it in an extension method so it'll operate on any IList<DateTime>, for example:
// purely an example, chances are this will have actual, y'know logic in live
public class DateRange
{
private List<DateTime> dates = new List<DateTime>();
public void Add(DateTime date)
{
this.dates.Add(date);
}
public IEnumerable<DateTime> Dates
{
get { return this.dates; }
}
}
public static IEnumerable<DateRange> GetRanges(this IList<DateTime> dates)
{
List<DateRange> ranges = new List<DateRange>();
DateRange currentRange = null;
// this presumes a list of dates ordered by day, if not then the list will need sorting first
for( int i = 0; i < dates.Count; ++i )
{
var currentDate = dates[i];
if( i == 0 || dates[i - 1] != currentDate.AddDays(-1))
{
// it's either the first date or the current date isn't consecutive to the previous so a new range is needed
currentRange = new DateRange();
ranges.Add(currentRange);
}
currentRange.Add(currentDate);
}
return ranges;
}
You could also make it even more generic by passing in an IEnumerable<DateTime>:
public static IEnumerable<DateRange> GetRanges(this IEnumerable<DateTime> dates)
{
List<DateRange> ranges = new List<DateRange>();
DateRange currentRange = null;
DateTime? previousDate = null;
// this presumes a list of dates ordered by day, if not then the list will need sorting first
foreach( var currentDate in dates )
{
if( previousDate == null || previousDate.Value != currentDate.AddDays(-1) )
{
// it's either the first date or the current date isn't consecutive to the previous so a new range is needed
currentRange = new DateRange();
ranges.Add(currentRange);
}
currentRange.Add(currentDate);
previousDate = currentDate;
}
return ranges;
}
dates.Aggregate(new List<DateRange>(), (acc, dt) =>
{
if (acc.Count > 0 && acc.Last().d2 == dt.AddDays(-1))
acc[acc.Count - 1].d2 = dt;
else
acc.Add(new DateRange(dt, dt));
return acc;
}
);
where DateRange is a class like this:
class DateRange
{
public DateTime d1, d2;
public DateRange(DateTime d1, DateTime d2)
{
this.d1 = d1;
this.d2 = d2;
}
}
var stringDates = new List<string> {"01/09/10", "31/08/10", "01/01/10"};
var dates = stringDates.ConvertAll(DateTime.Parse);
dates.Sort();
var lastDateInSequence = new DateTime();
var firstDateInSequence = new DateTime();
foreach (var range in dates.GroupBy(
d => { if ((d - lastDateInSequence).TotalDays != 1)
firstDateInSequence = d;
lastDateInSequence = d;
return firstDateInSequence;
}))
{
var sb = new StringBuilder();
sb.Append(range.First().ToShortDateString());
sb.Append(" => ");
sb.Append(range.Last().ToShortDateString());
Console.WriteLine(sb.ToString());
}

Get the previous month's first and last day dates in c#

I can't think of an easy one or two liner that would get the previous months first day and last day.
I am LINQ-ifying a survey web app, and they squeezed a new requirement in.
The survey must include all of the service requests for the previous month. So if it is April 15th, I need all of Marches request ids.
var RequestIds = (from r in rdc.request
where r.dteCreated >= LastMonthsFirstDate &&
r.dteCreated <= LastMonthsLastDate
select r.intRequestId);
I just can't think of the dates easily without a switch. Unless I'm blind and overlooking an internal method of doing it.
var today = DateTime.Today;
var month = new DateTime(today.Year, today.Month, 1);
var first = month.AddMonths(-1);
var last = month.AddDays(-1);
In-line them if you really need one or two lines.
The way I've done this in the past is first get the first day of this month
dFirstDayOfThisMonth = DateTime.Today.AddDays( - ( DateTime.Today.Day - 1 ) );
Then subtract a day to get end of last month
dLastDayOfLastMonth = dFirstDayOfThisMonth.AddDays (-1);
Then subtract a month to get first day of previous month
dFirstDayOfLastMonth = dFirstDayOfThisMonth.AddMonths(-1);
using Fluent DateTime https://github.com/FluentDateTime/FluentDateTime
var lastMonth = 1.Months().Ago().Date;
var firstDayOfMonth = lastMonth.FirstDayOfMonth();
var lastDayOfMonth = lastMonth.LastDayOfMonth();
DateTime LastMonthLastDate = DateTime.Today.AddDays(0 - DateTime.Today.Day);
DateTime LastMonthFirstDate = LastMonthLastDate.AddDays(1 - LastMonthLastDate.Day);
I use this simple one-liner:
public static DateTime GetLastDayOfPreviousMonth(this DateTime date)
{
return date.AddDays(-date.Day);
}
Be aware, that it retains the time.
An approach using extension methods:
class Program
{
static void Main(string[] args)
{
DateTime t = DateTime.Now;
DateTime p = t.PreviousMonthFirstDay();
Console.WriteLine( p.ToShortDateString() );
p = t.PreviousMonthLastDay();
Console.WriteLine( p.ToShortDateString() );
Console.ReadKey();
}
}
public static class Helpers
{
public static DateTime PreviousMonthFirstDay( this DateTime currentDate )
{
DateTime d = currentDate.PreviousMonthLastDay();
return new DateTime( d.Year, d.Month, 1 );
}
public static DateTime PreviousMonthLastDay( this DateTime currentDate )
{
return new DateTime( currentDate.Year, currentDate.Month, 1 ).AddDays( -1 );
}
}
See this link
http://www.codeplex.com/fluentdatetime
for some inspired DateTime extensions.
The canonical use case in e-commerce is credit card expiration dates, MM/yy. Subtract one second instead of one day. Otherwise the card will appear expired for the entire last day of the expiration month.
DateTime expiration = DateTime.Parse("07/2013");
DateTime endOfTheMonthExpiration = new DateTime(
expiration.Year, expiration.Month, 1).AddMonths(1).AddSeconds(-1);
If there's any chance that your datetimes aren't strict calendar dates, you should consider using enddate exclusion comparisons...
This will prevent you from missing any requests created during the date of Jan 31.
DateTime now = DateTime.Now;
DateTime thisMonth = new DateTime(now.Year, now.Month, 1);
DateTime lastMonth = thisMonth.AddMonths(-1);
var RequestIds = rdc.request
.Where(r => lastMonth <= r.dteCreated)
.Where(r => r.dteCreated < thisMonth)
.Select(r => r.intRequestId);
DateTime now = DateTime.Now;
int prevMonth = now.AddMonths(-1).Month;
int year = now.AddMonths(-1).Year;
int daysInPrevMonth = DateTime.DaysInMonth(year, prevMonth);
DateTime firstDayPrevMonth = new DateTime(year, prevMonth, 1);
DateTime lastDayPrevMonth = new DateTime(year, prevMonth, daysInPrevMonth);
Console.WriteLine("{0} {1}", firstDayPrevMonth.ToShortDateString(),
lastDayPrevMonth.ToShortDateString());
This is a take on Mike W's answer:
internal static DateTime GetPreviousMonth(bool returnLastDayOfMonth)
{
DateTime firstDayOfThisMonth = DateTime.Today.AddDays( - ( DateTime.Today.Day - 1 ) );
DateTime lastDayOfLastMonth = firstDayOfThisMonth.AddDays (-1);
if (returnLastDayOfMonth) return lastDayOfLastMonth;
return firstDayOfThisMonth.AddMonths(-1);
}
You can call it like so:
dateTimePickerFrom.Value = GetPreviousMonth(false);
dateTimePickerTo.Value = GetPreviousMonth(true);
var lastMonth = DateTime.Today.AddMonths(-1);
dRet1 = new DateTime(lastMonth.Year, lastMonth.Month, 1);
dRet2 = new DateTime(lastMonth.Year, lastMonth.Month, DateTime.DaysInMonth(lastMonth.Year, lastMonth.Month));

Categories

Resources