I'm trying to to take part of a string and set it as a date time property for a class. The date part of string is part of a textfile and formatted as dd/mm/yyyy.
My code works fine for other properties, string int etc but I'm experiencing an error when trying to use datetime. I cant pinpoint where the problem is.
An unhandled exception of type 'System.IndexOutOfRangeException'
occurred in Hospital.exe
Additional information: Index was outside the bounds of the array.''
//read files from file
string[] linesx = File.ReadAllLines("patients.txt");//creates array of each line in text file
string[] patientInfo = new string[4];
string[] dateInfo = new string[3];
string patientLong, name;
Patient newPatient;
int age,blood,x;
DateTime date;
int year, month, day;
//sort through text and get data.
for (int i = 0; i < linesx.Length; i++)
{
patientLong = linesx[i];//gets each lines details eg.ward,56
patientInfo = patientLong.Split(',');//separates info eg,ward ,56
name = patientInfo[0];//gets name from index 0
age = Convert.ToInt32(patientInfo[1]); //gets age from index1
blood = Convert.ToInt32(patientInfo[2]);
x = Convert.ToInt32(patientInfo[3]);
dateInfo = patientInfo[2].Split('/');
day = Convert.ToInt32(dateInfo[0]);
month = Convert.ToInt32(dateInfo[1]);
year = Convert.ToInt32(dateInfo[2]);
date = new DateTime(year, month, day);
newPatient = new Patient(name, age,blood,x,date);
patients.Add(newPatient);
}
I can see that
dateInfo = patientInfo[2].Split('/');
should be
dateInfo = patientInfo[4].Split('/');
You've messed int and DateTime formats:
Either patientInfo[2] is integer, e.g. 42, so you can put
blood = Convert.ToInt32(patientInfo[2]);
but can't
dateInfo = patientInfo[2].Split('/');
month = Convert.ToInt32(dateInfo[1]);
Or patientInfo[2] is DateTime, e.g. 10/11/1976, so you can't put
blood = Convert.ToInt32(patientInfo[2]);
Since you have 'System.IndexOutOfRangeExceptionexception,patientInfo[2]is of typeintand the most probable cause of the misbehaviour is a *typo*: it'spatientInfo[4]that storesdate, notpatientInfo[2]`.
As for implementation, it's one of the problem Linq has been designed for:
using System.Linq;
....
List<Patient> patients = File
.ReadLines("patients.txt")
.Select(line => line.Split(','))
.Select(items => new Patient(
items[0],
int.Parse(items[1]),
int.Parse(items[2]),
int.Parse(items[3]),
DateTime.ParseExact(items[4], "d/M/yyyy", CultureInfo.InvariantCulture)
))
.ToList();
Related
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.
I have a .netapp application (C#) that I use to extract data from an API.
It is having a problem just now as we are running this for December 2017.. but we want it to name as January 2018. (well 01/01/2018)
I think they way we have written it means it's looking for 13/2017 which obviously doesn't exist.
Can anyone recommend how to ammend this so we can run it just now and how we can ensure we don't run into this issue again next December?
public override string ToString()
{
var reportDate = new DateTime(DateTime.Now.Year, DateTime.Now.Month + 1, 1);
if (!String.IsNullOrWhiteSpace(AppConfigHelper.EndDate))
{
var year = Int32.Parse(AppConfigHelper.EndDate.Substring(6, 4));
var month = Int32.Parse(AppConfigHelper.EndDate.Substring(3, 2));
var day = Int32.Parse(AppConfigHelper.EndDate.Substring(0, 2));
reportDate = new DateTime(year, month, day);
reportDate = reportDate.AddDays(1);
}
You can use DateTime.Today.AddMonths(1):
var nextMonth = DateTime.Today.AddMonths(1);
reportDate = new DateTme(nextMonth.Year, nextMonth.Month, 1);
// ...
By the way, you don't need string methods and int.Parse to get the DateTime, use ParseExact:
if (!String.IsNullOrWhiteSpace(AppConfigHelper.EndDate))
{
reportDate = DateTime.ParseExact(AppConfigHelper.EndDate, "ddMMyyyy", null);
reportDate = reportDate.AddDays(1);
}
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);
I have some files with this pattern:
PrefixyyyyMMddHHmmss.txt
That Prefix is always the same.
For example :
Prefix20120830115800.txt
Prefix20120829114200.txt
Prefix20120829134621.txt
I want to write a function to get one day and range and returns all files that their names are in input range from that day:
ReadFiles(string filesLocation, DateTime fromDate, int range)
Now I use this approach:
for (int i = 0; i <= range; i++)
{
SearchFolderForFiles(location, fromDate.AddDays(i));
}
SearchFolderForFiles(//params)
{
//…
string searchTemplate = string.Format("Prefix{0:yyyyMMdd}*.txt", date);
DirectoryInfo di = new DirectoryInfo(location);
FileInfo[] myFiles = di.GetFiles(searchTemplate);
//…
}
But I think it should be better way(specially we have range not separated days)
Thanks
You could do it with linq.
Horrible example, but you can see what i'm getting at :)
DateTime startDate = DateTime.Now;
DateTime endDate = DateTime.Now;
var myFiles = new DirectoryInfo(location).EnumerateFiles()
.Where(f => DateTime.Parse(System.IO.Path.GetFileNameWithoutExtension(f.Name).Replace("Prefix", "")) >= startDate
&& DateTime.Parse(System.IO.Path.GetFileNameWithoutExtension(f.Name).Replace("Prefix", "")) <= endDate);
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));