How to display opening times? - c#

I'm trying to show intervals of working hours/days it's should look like this:
(source: clip2net.com)
I have table where I'm storing day number, open time and closing time for each day
(source: clip2net.com)
Then I created query=>
var groups = from s in this.OpenTimes
orderby s.Day
group s by new { s.Till, s.Start } into gr
select new
{
Time = gr.Key.Start + "-" + gr.Key.Till,
Days = this.OpenTimes
.Where(o => o.Start == gr.Key.Start && o.Till == gr.Key.Till)
.OrderBy(d => d.Day).Select(d => d.Day).ToArray()
};
This query provides all grouped time intervals and days that included to this time-range
But I faced with problem - I created second half that representing this groups, but it's not working properly.
Maybe somebody could explain to me needed point of vision or this basic logic of showing opening times.
Thanks in advice...

Next approach works for me:
result screen
public string OpeningTimesString
{
get
{
if (!this.OpeningTimes.IsLoaded)
this.OpeningTimes.Load();
var groups = (from s in this.OpeningTimes
orderby s.Day, s.Start, s.Stop
group s by new { Stop = formatTime(s.Stop), Start = formatTime(s.Start), s.Day } into gr
select new
{
Time = gr.Key.Start + "-" + gr.Key.Stop,
Day = gr.Key.Day
}).ToList();
string result = "";
int tmp = 1;
for (int i = 0; i < groups.Count(); i++)
{
//One one = new One();
bool exit = false;
tmp = i;
while (exit == false)
{
if (i + 1 < groups.Count && groups[i].Time.Equals(groups[i + 1].Time))
{
i++;
}
else
{
if (tmp != i)
result += (NormalDayOfWeek)(groups[tmp].Day - 1) + "-" + (NormalDayOfWeek)(groups[i].Day - 1) + " : " + groups[i].Time + "<br />";
else
result += (NormalDayOfWeek)(groups[i].Day - 1) + " : " + groups[i].Time + "<br />";
exit = true;
}
}
}
if (result.IsNotNull())
return result;
else
return "[%Not yet defined]";
}
}

Related

I'm curious about the logic that checks only once at a certain time

I would like help.
There are some problems with the code.
I want to do only one inspection at a certain time every day.
In particular, the problem is the most serious in DateTime.Now.Hour == 11 part.
I am having difficulty checking certain times. I need to write code that can be checked only once at 11:00 in the whlie statement.
I created a license file and checked the date of the file.
public static CResult Dailytime(string date)
{
CResult result = new CResult();
if(result.nRet == 0)
{
while (true)
{
if (result.nRet == 1 || result.nRet == 2)
{
return result;
}
if (DateTime.Now.Hour == 11)
{
result = DailyCheckData(date);
if(result.nRet == 1 || result.nRet == 2)
{
return result;
}
}
System.Threading.Thread.Sleep(60 * 30 * 1000);
}
}
return result;
}
public static CResult DailyCheckData(string data)
{
CResult result = new CResult();
DateTime licenseDate = Convert.ToDateTime(data);
string dateNow = DateTime.Now.ToString("yyyy-MM-dd");
int compareDate = DateTime.Compare(Convert.ToDateTime(data), DateTime.Now);
if (licenseDate.ToString("yyyy-MM-dd") == dateNow)
{
result = ExpirationCertificate();
Console.WriteLine("Result = " + result.Result + " Msg = " + result.Msg + " nRet = " + result.nRet);
return result;
}
else
{
if (compareDate > 0)
{
result = TrueCertificate();
Console.WriteLine("Result = " + result.Result + " Msg = " + result.Msg + " nRet = " + result.nRet);
}
else if (compareDate <= 0)
{
result = ExpirationCertificate();
Console.WriteLine("Result = " + result.Result + " Msg = " + result.Msg + " nRet = " + result.nRet);
}
return result;
}
}
CResult class
nRet= 0 or 1 or 2
0 = fasle date
1 = false file
2 = true
Suggest or suggest ways to improve.
Can you try create a variable for DateTime.Now, after a line of code that value change.
DateTime licenseDate = Convert.ToDateTime(data);
string dateNow = DateTime.Now.ToString("yyyy-MM-dd");
int compareDate = DateTime.Compare(Convert.ToDateTime(data), DateTime.Now);
To
DateTime licenseDate = Convert.ToDateTime(data);
var now = DateTime.Now;
string dateNow = now.ToString("yyyy-MM-dd");
int compareDate = DateTime.Compare(licenseDate, now);
you shouldn't use Thread.Sleep() method for such a long duration. It is poor programming logic to make the thread sleep for such a long period.
What you can do to solve this is, is to make a Timer. There's an example attached in the link. A simple snippet to match your logic would be:
licenseStart = //setYours
lastCheck = DateTime.Now;
nextCheck = now.AddDays(1); // now.AddHours(1)
var timer = new Timer(o=>{/* Do work*/}, null, TimeSpan.Zero, nextCheck);
Hope it helps!
I asked about logic that can only loop once at 11 o'clock.
But I could not find the right answer and I found the answer.
I do not speak English well.
That's why others do not understand the intent of the question.
bool bOnce = true;
//bool s0nce = true;
while (true)
{
if (DateTime.Now.Hour == 11 && bOnce)
{
//run code
}
if (bOnce == true)
bOnce = false;
else
bOnce = true;
Thread.Sleep(10 * 60 * 1000);
}

compare List with different size in C#

Hi I have an application in C# .NET where a person can submit an abstract. It will be a paragraph.
Now if I made any changes on that abstract from my end, It should send the email to that person with the Original abstract and modified abstract. Where in Modified section it should highlight the changes done.
I have written a function for this:
public string[] compareText(string submittedValue,string updatedValue)
{
#region COMPARETEXT
List<string> oldAbstract = submittedValue.Split('.').ToList<string>();
List<string> newAbstract = updatedValue.Split('.').ToList<string>();
string resultOldAbstract = "";
string resultNewAbstract = "";
for (var i = 0; i < (oldAbstract.Count - 1); i++)
{
if (String.Equals(oldAbstract[i], newAbstract[i], StringComparison.Ordinal))
{
resultOldAbstract += oldAbstract[i].ToString() + ".";
resultNewAbstract += newAbstract[i].ToString() + ".";
}
else
{
List<string> oldAbstract1 = oldAbstract[i].Split(' ').ToList<string>();
List<string> newAbstract1 = newAbstract[i].Split(' ').ToList<string>();
if (oldAbstract1.Count == newAbstract1.Count)
{
for (var j = 0; j < (oldAbstract1.Count); j++)
{
if (String.Equals(oldAbstract1[j], newAbstract1[j], StringComparison.Ordinal))
{
if (j < (oldAbstract1.Count - 1))
{
resultOldAbstract += oldAbstract1[j].ToString() + " ";
resultNewAbstract += newAbstract1[j].ToString() + " ";
}
else
{
resultOldAbstract += oldAbstract1[j].ToString() + ".";
resultNewAbstract += newAbstract1[j].ToString() + ".";
}
}
else
{
if (j < (oldAbstract1.Count - 1))
{
resultOldAbstract += oldAbstract1[j].ToString() + " ";
resultNewAbstract += "<span style='background:yellow'>" + newAbstract1[j].ToString() + "</span> ";
}
else
{
resultOldAbstract += oldAbstract1[j].ToString() + ".";
resultNewAbstract += "<span style='background:yellow'>" + newAbstract1[j].ToString() + "</span>.";
}
}
}
}
else
{
resultOldAbstract += oldAbstract[i].ToString() + ".";
resultNewAbstract += "<span style='background:yellow'>" + newAbstract[i].ToString() + "</span>.";
}
}
}
//return resultOldAbstract,resultNewAbstract;
return new[] {resultOldAbstract,resultNewAbstract};
#endregion
}
but it only works when the size of both list are same. For e.g.
****Submitted abstract****
hi This is John. i am 26 year old. I live in New York.
****Updated abstract****
Hi This is John. I am 26 year old. I live in washington.
when I do these changes then It works fine. It highlights the changes done at hi, i, New York.
Here the submitted list and updated list both have same number of elements ( here it is 3 , bcz i am splitting at fullstop '.'). But suppose in my update abstract I add a new line or remove a line:
****Updated abstract****
Hi This is John. I am 26 year old. I live in washington. I am a software engineer.
or
****Updated abstract****
Hi This is John. I am 26 year old.
then it does not work because the size of list is different and in for loop it throws index error.
Any thoughts ?

why does it appear a blank space between to string concatened c#

public string completeHour(string theTime)
{
string total="";
string[] timeArray = theTime.Split(new[] { ":" }, StringSplitOptions.None);
string h = timeArray[0];
string i = timeArray[1];
string j = timeArray[2];
MessageBox.Show(h + "+" + i + "+" + j);
if (h == " " || i == " " || j == " ")
{
if (h == " ")
{
h = "00";
total = (String.Concat("00",theTime)).Trim();
MessageBox.Show(total);
}
else if (i == " ")
{
i = "00";
total = timeArray[0] + i + timeArray[2];
//MessageBox.Show("m-=" + total);
}
//else if (j == "")
//{
// j = "00";
// theTime = timeArray[0] + timeArray[1] + j;
// MessageBox.Show("s-=" + theTime);
//}
}
return total;
}
Why total is 00 :52:04 (for instance) and not 00:52:04 that was supposed to be?
If you'd like to make sure there are no leading or trailing white characters, you could call
string h = timeArray[0].Trim();
And then instead of checking the value against " ", you could compare it to String.Empty or call h.IsNullOrEmpty().
However I'd strongly recommend you to use simpler approach, using a DateTime object.
DateTime timeObject;
DateTime.TryParse(theTime, out timeObject);
and then just work with Hour, Minute and Second properties. This way you get away from custom parsing and make your code more object-oriented, thus easier to read, instead of juggling multiple string objects.
Best way to avoid this is using Trim() when assigning value to total in following two lines:
total = (String.Concat("00",theTime.Trim())).Trim();
.
.
.
total = timeArray[0].trim() + i + timeArray[2].Trim();
Although I was using a MaskedTextBox I didn't define a custom mask so, anywhere (I think) the system assumed that 'theTime' was the type of DateTime.
So, the result of String.Concat("00",theTime) was '00 :32:99', for instance.
I´ve solved it by using the variables h, i and j instead of theTime.
Using a DateTime variable was not appropriated because I want to allow the user to insert NULL values for the hours or for the minutes.

best comparison algorithm for finding meeting times . (Dictionary collection)

I.m using c# language .I have a dictionary. the key is string of peoples emails. The value for each key is a list of objects. Those objects has 2 dateTime variables start and End.
What I'm trying to do is finding when is the time that all people I have are free. in addition to finding the times if some of them are available.
I managed to solve the first part which when all users are available. However, since I'm using a linear search the code is really slow.
so my questions are:
What is the better algorithm for doing this kind of comparison, keep in mind I'm comparing date ranges.
What is the best way to find if some of them are available at a specific time ??
This is the method responsible for intersection
private static FreeTime Intersection(FreeTime first, FreeTime second)
{
Console.WriteLine("inside intersection " + first.Start + " "+ first.End + " sescond " + second.Start + " " + second.End);
int result1 = DateTime.Compare(first.Start, second.End);
int result2 = DateTime.Compare(first.End, second.Start);
int result3 = DateTime.Compare(first.Start, second.Start);
int result4 = DateTime.Compare(first.End, second.End);
Boolean equal = (result3 == 0 && result4 == 0);
if (!(result1 >= 0) && !(result2 <= 0) && !equal)
{
Console.WriteLine(new DateTime(Math.Max(first.Start.Ticks, second.Start.Ticks)).TimeOfDay + "min max" + new DateTime(Math.Min(first.End.Ticks, second.End.Ticks)).TimeOfDay);
return new FreeTime(new DateTime(Math.Max(first.Start.Ticks, second.Start.Ticks)), new DateTime(Math.Min(first.End.Ticks, second.End.Ticks)));
}
else if (result3 == 0 && result4 == 0)
return (new FreeTime(first.Start, first.End));
else return null;
This part is for iterating through the lists
foreach (var t in allFree)
{
if (allFree != null)///&& list.Count > 1)
{
Console.WriteLine(t.Start + " " + t.End + " in all freeeee");
foreach (var s in allFree)
{
if (!((DateTime.Compare(t.Start.Date, s.Start.Date) == 0) && (DateTime.Compare(t.Start, s.Start) == 0) && (DateTime.Compare(t.End, s.End) == 0)) && (t.Start.Date == s.Start.Date))
{
Console.WriteLine("callling inteersection 2 ");
intersection = Intersection(t, s);
}
// else if ((list.Count == list2.Count) && ((DateTime.Compare(t.Start.Date, s.Start.Date) == 0) && (DateTime.Compare(t.Start, s.Start) == 0) && (DateTime.Compare(t.End, s.End) == 0)) && (t.Start.Date == s.Start.Date))
// intersection = new FreeTime(t.Start, t.End);
if (intersection != null)
{
finalFree.Add(intersection);
Console.WriteLine(intersection.Start + " " + intersection.End + " intersection result");
intersecFound = true;
}
}//end foreach
if (!intersecFound)
{
// allFree.Add(t);
intersecFound = false;
}

Loop takes too long to execute (looping through 365 days a year) [closed]

This question is unlikely to help any future visitors; it is only relevant to a small geographic area, a specific moment in time, or an extraordinarily narrow situation that is not generally applicable to the worldwide audience of the internet. For help making this question more broadly applicable, visit the help center.
Closed 9 years ago.
I have a list of manpower (40 people). I need to loop through a year (365 days) for each person to extract data for each day. But this takes too much time. Is there any suggestion to improve speed or a different method?
for (int man=0;man<40;man++)
{
for (DateTime date = DateTime.Now.Date;date<DateTime.Now.AddYears(1);date=date.AddDays(1))
{
//do stuff
}
}
EDIT: Stuff involves extracting data from a database where i get Projects each person is involved in, and start and end dates of the projects per person. (Each person has his own table and there is a master table with a list of all men). I have a datagridview, in which I show 40 men in the vertical axis. 365 days in the horizontal. Depending on the no. of projects, each person is involved in, I need to colourcode the corresponding cell.
EDIT 2:
//A is a class that connects to a database, forwards a query and returns the result
void colourchanger()
{
for (int m = 0; m < i; m++)//i=40
{
int copy = m;
List<string>[] list = new List<string>[5];
int number = A.Countproj(abc);//return no. of projects under man
list = A.manprojselect(abc);//returns project details
thread[copy] = new Thread(() => threader(copy,2*copy,list,number));
thread[copy].Start();
}
}
void threader(int p, int x,List<string>[] list,int numberer)
{
DateTime labeldate;
DataGridViewCellStyle AL = new DataGridViewCellStyle();
AL.BackColor = Color.Brown;//AL
DataGridViewCellStyle NS = new DataGridViewCellStyle();
NS.BackColor = Color.Aqua;//NS
DataGridViewCellStyle training = new DataGridViewCellStyle();
training.BackColor = Color.Maroon;//training
DataGridViewCellStyle one = new DataGridViewCellStyle();
one.BackColor = Color.Green;//one project
DataGridViewCellStyle overseas = new DataGridViewCellStyle();
overseas.BackColor = Color.Blue;//overseas
DataGridViewCellStyle two = new DataGridViewCellStyle();
two.BackColor = Color.Yellow;//2 projects
DataGridViewCellStyle three = new DataGridViewCellStyle();
three.BackColor = Color.Red;//3 projects
DataGridViewCellStyle unfeasible = new DataGridViewCellStyle();
unfeasible.BackColor = Color.Black;//self explanatory
DataGridViewCellStyle none = new DataGridViewCellStyle();
none.BackColor = Color.Gray;//self explanatory
string[] projname;
string[] country;
string[] start;
string[] end;
string temp;
DateTime startdate;
DateTime enddate;
int[] track = new int[366];
string[] projnames = new string[366];
for (int y = 0; y < 366; y++)
{
projname = list[0].ToArray();
country = list[2].ToArray();
start = list[3].ToArray();
end = list[4].ToArray();
temp = dataGridView1.Rows[x].Cells[y].ToolTipText;
temp = temp[0].ToString() + temp[1].ToString() + temp[2].ToString() + temp[3].ToString() + temp[4].ToString() + temp[5].ToString() + temp[6].ToString() + temp[7].ToString() + temp[8].ToString() + temp[9].ToString();
labeldate = DateTime.ParseExact(temp,
"dd-MM-yyyy",
CultureInfo.InvariantCulture);
for (int l = 0; l < numberer; l++)
{
startdate = DateTime.ParseExact(start[l],
"dd-MM-yyyy HH:mm:ss",
CultureInfo.InvariantCulture);
enddate = DateTime.ParseExact(end[l],
"dd-MM-yyyy HH:mm:ss",
CultureInfo.InvariantCulture);
int r1 = DateTime.Compare(startdate, labeldate);
int r2 = DateTime.Compare(labeldate, enddate);
if (r1 <= 0 && r2 <= 0)
{
track[y]++;
projnames[y] = projnames[y] + ", " + projname[l];
if (String.Compare(country[l], "Singapore ") != 0)
{
track[y] = 10;
projnames[y] = " " + projname[l];
}
if (String.Compare(projname[l], "ANNUAL LEAVE") == 0)
{
track[y] = 20;
projnames[y] = " " + projname[l];
}
if (String.Compare(projname[l], "NATIONAL SERVICE") == 0)
{
track[y] = 30;
projnames[y] = " " + projname[l];
}
if (String.Compare(projname[l], "TRAINING") == 0)
{
track[y] = 40;
projnames[y] = " " + projname[l];
}
}
}
}
for (int y = 0; y < 366; y++)
{
if (track[y] == 0)
{
dataGridView1.Rows[x].Cells[y].Style = none;
dataGridView1.Rows[x].Cells[y].ToolTipText = dataGridView1.Rows[x].Cells[y].ToolTipText + projnames[y];
}
if (track[y] == 1)
{
dataGridView1.Rows[x].Cells[y].Style = one;
dataGridView1.Rows[x].Cells[y].ToolTipText = dataGridView1.Rows[x].Cells[y].ToolTipText + projnames[y];
}
if (track[y] == 2)
{
dataGridView1.Rows[x].Cells[y].Style = two;
dataGridView1.Rows[x].Cells[y].ToolTipText = dataGridView1.Rows[x].Cells[y].ToolTipText + projnames[y];
}
if (track[y] == 3)
{
dataGridView1.Rows[x].Cells[y].Style = three;
dataGridView1.Rows[x].Cells[y].ToolTipText = dataGridView1.Rows[x].Cells[y].ToolTipText + projnames[y];
}
if (track[y] == 10)
{
dataGridView1.Rows[x].Cells[y].Style = overseas;
dataGridView1.Rows[x].Cells[y].ToolTipText = dataGridView1.Rows[x].Cells[y].ToolTipText + projnames[y];
}
if (track[y] == 20)
{
dataGridView1.Rows[x].Cells[y].Style = AL;
dataGridView1.Rows[x].Cells[y].ToolTipText = dataGridView1.Rows[x].Cells[y].ToolTipText + projnames[y];
}
if (track[y] == 30)
{
dataGridView1.Rows[x].Cells[y].Style = NS;
dataGridView1.Rows[x].Cells[y].ToolTipText = dataGridView1.Rows[x].Cells[y].ToolTipText + projnames[y];
}
if (track[y] == 40)
{
dataGridView1.Rows[x].Cells[y].Style = training;
dataGridView1.Rows[x].Cells[y].ToolTipText = dataGridView1.Rows[x].Cells[y].ToolTipText + projnames[y];
}
if (track[y] > 3 && (track[y] != 10 && track[y] != 20 && track[y] != 30 && track[y] != 40))
{
dataGridView1.Rows[x].Cells[y].Style = unfeasible;
dataGridView1.Rows[x].Cells[y].ToolTipText = dataGridView1.Rows[x].Cells[y].ToolTipText + projnames[y];
}
}
}
DB used: SQL CE
EDIT 3: Manprojselect() posted
public List<string>[] manprojselect(string manpowername)
{
string query = "SELECT * FROM "+ manpowername;
//Create a list to store the result
List<string>[] list = new List<string>[5];
list[0] = new List<string>();
list[1] = new List<string>();
list[2] = new List<string>();
list[3] = new List<string>();
list[4] = new List<string>();
//Open connection
if (this.OpenConnection() == true)
{
//Create Command
SqlCeCommand cmd = new SqlCeCommand(query, connection);
//Create a data reader and Execute the command
SqlCeDataReader dataReader = cmd.ExecuteReader();
//Read the data and store them in the list
while (dataReader.Read())
{
list[0].Add(dataReader["Name"] + "");
list[1].Add((dataReader["Allotment_number"]).ToString() + "");
list[2].Add(dataReader["Country"] + "");
list[3].Add(dataReader["Start_date"] + "");
list[4].Add(dataReader["End_date"] + "");
}
//close Data Reader
dataReader.Close();
//close Connection
this.CloseConnection();
//return list to be displayed
return list;
}
else
{
return list;
}
}
It only loops 365*40 times, and it's a simple check. All your slowdown beyond that is being caused by //do stuff.
I'd add that this is actually a common problem - the length of time it takes to //do stuff is then multiplied by 365*40 (assuming stuff is takes a consistent amount of time over people and days).
Try to extract data from database as a single bulk query or at least single query per person.
Analyze your data in code and even with unoptimized code it will work much faster than query for each cell.
As stated, //do stuff is the culprit.
Without any more information, I can only suggest you try to use the Parallel.For method and make use of more threads (useful if you have more than one logical CPU core available).
Just remember that this will require you to take lock into consideration, as concurrent access to shared variables might cause problems.
Just for fun. How could I optimize that loop? I have tried with this
void Main()
{
Stopwatch sw = new Stopwatch();
sw.Start();
int max = DateTime.Today.AddYears(1).Subtract(DateTime.Today).Days;
for (int man=0;man<40;man++)
{
for (int x = 0; x <= max; x++)
{
//do stuff
}
}
sw.Stop();
Console.WriteLine(sw.Elapsed.TotalMilliseconds);
sw.Reset();
sw.Start();
for (int man=0;man<40;man++)
{
for (DateTime date = DateTime.Now.Date;date<DateTime.Now.AddYears(1);date=date.AddDays(1))
{
//do stuff
}
}
sw.Stop();
Console.WriteLine(sw.Elapsed.TotalMilliseconds);
}
First loop calculates the length in days of a year and then loops with an integer, the second one is the OP.
The first loop is an astounding 19 milliseconds faster.
Well, enough fun, back to work and try to optimize that do stuff
Your problem is that you try to do 365*40 separate queries to the database. Typically, you want more of this to be evaluated server side.
To answer your direct question: yes, you can make the code go faster. This will not, however, solve your problem.
You can store the current date to a local variable and then use it instead of doing all those calls to DateTime.Now, which will check the system time each time.
var now=DateTime.Now;
var yearFromNow = DateTime.Now.AddYears(1);
... and then use these new variables in your loop.
You can also store all the dates in a list, reducing the number of calculations needed inside the loop:
var dates = Enumerable.Range(0,365).Select(n=>now.AddDays(n)).ToList();
Then you can access this list in the loop:
for (int man=0;man<40;man++)
{
foreach (var dt in dates)
{
//do stuff
}
}
... but this is not where your main performance problem is. Instead, you should post the //do stuff body here, and possibly the type of db access you are using (LINQ2Sql,EF etc) so we can see if the whole thing can be optimized for significant gain.
The connection should not be re-opened for each loop pass.

Categories