Ok im sitting with this issue kind of stupid but I don't know how to google this for the solution.
Lets say i have a database with values inside e.g 1000.00 .
I convert it to double using Convert.ToDouble();
On my PC it works, however on my server it doesn't unless I change to string and replace . with , .
i.e 1000,00 works on the Server but not 1000.00
But if I do Convert 1000,00 to Double I cannot save it again in the database without taking it back to string and replace , with .
How can I overcome this problem.
OS is win7, server is SQL Server 2012.
DataTable DT = SQLServer.ExecuteQueryWithResults("EXEC CalculateMonthlyBallance");
foreach (DataRow row in DT.Rows)
{
ClientCompany CC = Data.Companies.First(C => C.CompanyID == row[0].ToString());
Finance Saldo = new Finance(CC.CompanyID, "Monthly Saldo", "Monthly Saldo", 0, 0, new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1), F_Type.Saldo, -1);
double rv = row[3].ToDouble();
MessageBox.Show("Company ID : " + CC.CompanyID.ToString() + " " + rv.ToString());
if (rv > 0)
{
Saldo.Debit = rv;
}
else if (row[3].ToDouble() < 0)
{
Saldo.Credit = -rv;
}
MessageBox.Show(Saldo.Debit + " " + Saldo.Credit);
CC.Finances = RetrieveFinances(CC.CompanyID).ToList();
if (CC.Finances.Count(S => (S.F_Type == F_Type.Saldo) && (S.Date == new DateTime(DateTime.Now.Year, DateTime.Now.Month, 1))) == 0)
{
CC.Finances.Add(Saldo);
CaptureFinancial(Saldo);
}
}
The locale setting, specifically the regional settings that govern what symbol is used as a decimal point, are influencing the conversion. To avoid that, you need to perform a culture invariant conversion so that the locale setting on your machine does not play a part. For example:
double value = double.Parse(stringValue, CultureInfo.InvariantCulture);
That said, I do wonder why you are storing floating point values as strings in the first place. It's best to convert user input into its natural form at the earliest possible moment, and only convert back to string as late as possible.
See Convert.ToDouble(string,CultureInfo)
This is because of your CultureInfo. Apparently, your PC is using periods for decimal notation, while your server is using commas. if you try to convert one of them using the other method, you get this issue.
Solution: Convert.ToDouble() has an extra overload which allows you to pass a cultureInfo for conversion. Or you can just save your variable in the database as a float or decimal.
Related
I have a problem. I need to sum hours worked in an office in a code. The dates i get from SQL server thats no problem but i have different formats. For example: 2019. 09. 23. 14:54:23, 2019.09.23 14:54:23 or 2019-09-23 14:54:23; And i want to sum hours worked in result. No matter the year. Heres the example:
try
{
string betölt = "SELECT * from munkaorak where";
if (cbTech.Text != "")
{
betölt += " Munkaszam='" + cbMunka.Text + "' AND Részfolyamat='" + cbRész.Text + "' AND TechKod='" + cbTech.Text + "'";
}
else if (cbRész.Text != "")
{
betölt += " Munkaszam='" + cbMunka.Text + "' AND Részfolyamat='" + cbRész.Text + "'";
}
else if(cbMunka.Text !="")
{
betölt += " Munkaszam='" + cbMunka.Text + "'";
}
betölt += " order by ID DESC";
MySqlCommand name = new MySqlCommand(betölt, kapcsolat);
kapcsolat.Open();
olvasó = name.ExecuteReader();
int összora = 0;
if (olvasó.HasRows)
{
while (olvasó.Read())
{
if (olvasó.GetString(7) != "Befejezés: ")
{
string[] aha = olvasó.GetString(6).Split(' ');
string kezdes = aha[4];
string[] kezd = kezdes.Split(':');
int kezdoido = Convert.ToInt32(kezd[0]) * 60 * 60 + Convert.ToInt32(kezd[1]) * 60 + Convert.ToInt32(kezd[2]);
int befejezoido = 0;
string aha22 = "";
if (olvasó.GetString(7).IndexOf('-') >= 0)
{
string[] aha2 = olvasó.GetString(7).Split(' ');
string befejezes = aha2[1];
string[] bef = befejezes.Split(':');
aha22 = aha2[0].Split('-')[2];
befejezoido = Convert.ToInt32(bef[0]) * 60 * 60 + Convert.ToInt32(bef[1]) * 60 + Convert.ToInt32(bef[2]);
}
else
{
string[] aha2 = olvasó.GetString(7).Split(' ');
string befejezes = aha2[4];
string[] bef = befejezes.Split(':');
aha22 = aha2[3];
befejezoido = Convert.ToInt32(bef[0]) * 60 * 60 + Convert.ToInt32(bef[1]) * 60 + Convert.ToInt32(bef[2]);
}
string dolgozott = "";
if (aha[3].Replace(".", "") == aha22.Replace(".", ""))
{
dolgozott = mpbolora(befejezoido - kezdoido);
összora += befejezoido - kezdoido;
}
else
{
dolgozott = mpbolora((86400 - kezdoido) + befejezoido);
összora += (86400 - kezdoido) + befejezoido;
}
string validalo = "";
try
{
string[] validal = olvasó.GetString(9).Split(' ');
validalo = validal[0] + " " + validal[1] + " " + validal[2] + validal[3] + validal[4] + " " + validal[5];
}
catch
{
validalo = olvasó.GetString(9);
}
string munkafolyamat = olvasó.GetString(3) + "-" + olvasó.GetString(4) + "-" + olvasó.GetString(5);
string[] sorok = { olvasó.GetString(2), dolgozott, olvasó.GetString(6).Replace("Kezdés: ", ""), olvasó.GetString(7).Replace("Befejezés: ", ""), olvasó.GetString(8), validalo, munkafolyamat };
var lv = new ListViewItem(sorok);
lvStat.Items.Add(lv);
}
}
}
else
{
kapcsolat.Close();
MessageBox.Show("Nincs adat!", "Figyelem");
}
kapcsolat.Close();
lblÖssz.Text = "Összesen ledolgozott órák: " + mpbolora(összora);
}
catch (Exception a)
{
MessageBox.Show(a.Message);
kapcsolat.Close();
}
kapcsolat.Close();
It worked but when different formats appeared its not working because '-' or spaces. Please help!
In C#, there is a bunch of methods provided to convert strings that contain date times in many formats into a unified DateTime object. These methods can recognize quite a few standard date time formats, and if yours differ from them, you can even provide your own.
DateTime.Parse() - Converts a string to a DateTime object. If operation fails, it'll thrown an exception.
DateTime.TryParse() - Converts a string to a DateTime object only if possible. Returns true if successful, and false if it fails.
DateTime.TryParseExact() - Converts a string that is in the specified format into a DateTime object. Returns true if successful, and false otherwise.
In your case, you can use DateTime.TryParse() (which is recommended over simply using DateTime.Parse() unless you're absolutely sure the format is correct) like so:
var dtStr1 = " 2019. 09. 23. 14:54:23";
var dtStr2 = "2019.09.23 14:54:23";
var dtStr3 = "2019-09-23 14:54:23";
DateTime.TryParse(dtStr1, out DateTime dt1);
DateTime.TryParse(dtStr2, out DateTime dt2);
DateTime.TryParse(dtStr3, out DateTime dt3);
Once converted to a DateTime object, it no longer has a format associated with it. It's a structure, and hence only has member variables and methods. So to calculate total hours etc. you can use provided methods.
Say you want to calculate time between day's work start and end. You can convert those into DateTime objects, then subtract one from the others which will give you a TimeSpam object.
var dtStrStart = "2019.09.23 08:23:12";
var dtStrEnd = "2019.09.23 16:17:28";
DateTime.TryParse(dtStrStart, out DateTime dtStart);
DateTime.TryParse(dtStrEnd, out DateTime dtEnd);
var diff = dtEnd - dtStart;
Now the TimeSpan object, which is diff here, will give you a bunch of properties with difference in hours, minutes etc.
The TimeSpan.Days, TimeSpan.Minutes etc will give you the time in days, minutes etc.
Console.WriteLine(diff.Days);
Console.WriteLine(diff.Hours);
Console.WriteLine(diff.Minutes);
Console.WriteLine(diff.Seconds);
Console.WriteLine(diff.Milliseconds);
Output:
0
7
54
16
0
The TimeSpan.TotalMinutes etc will give you the entire time period in respective units.
Console.WriteLine(diff.TotalDays);
Console.WriteLine(diff.TotalHours);
Console.WriteLine(diff.TotalMinutes);
Console.WriteLine(diff.TotalSeconds);
Console.WriteLine(diff.TotalMilliseconds);
Output:
0.329351851851852
7.90444444444444
474.266666666667
28456
28456000
And conversely, when you're storing data in the database, you must again use a standard format, such as datetime or datetime2. It's advised you use datetime2, more info here.
Your code should look more like this:
try
{
MySqlCommand name = new MySqlCommand("SELECT * from munkaorak WHERE Munkaszam=#m", kapcsolat);
name.Parameters.AddWithValue("#m", cbMunka.Text);
if (cbRész.Text != "")
{
name.CommandText += " AND Részfolyamat=#r";
name.Parameters.AddWithValue("#r", cbRész.Text);
}
if (cbTech.Text != "")
{
name.CommandText += " AND TechKod=#t";
name.Parameters.AddWithValue("#t", cbTech.Text);
}
name.CommandText += " order by ID DESC"; //is it really necessary?
MySqlDataAdapter da = new MySqlDataAdapter(name);
DataTable dt = new DataTable();
da.Fill(dt);
foreach(DataRow ro in dt.Rows){
string fromStr = ro["YOUR_FROM_DATE_COLUMN_NAME"].ToString();
//cope with dates in varying formats
//by replacing all non-numeric chars with nothing
fromStr = Regex.Replace(fromStr, #"[^0-9]", "");
//now our dates of [2019. 09. 23. 14:54:23], [2019.09.23 14:54:23] or [2019-09-23 14:54:23]
//just become 20190923145423
DateTime fromDt = DateTime.ParseExact(fromStr, "yyyyMMddHHmmss", CultureInfo.InvariantCulture);
string toStr = ro["YOUR_TO_DATE_COLUMN_NAME"].ToString();
toStr = Regex.Replace(toStr, #"[^0-9]", "");
DateTime toDt = DateTime.ParseExact(toStr, "yyyyMMddHHmmss", CultureInfo.InvariantCulture);
//total hours worked
(toDt - fromDt).TotalHours;
}
}
Hopefully that looks a lot simpler
Here you see no..:
Risky SQL injection hack possibility - don't concatenate values into your SQL, ever. Always concatenate a parameter in and then give a value to the parameter. Always
Difficult to read, lengthy string concatenation - looks terrible, always avoid it if you can
DB Connection opening and closing - micromanaging the database connection isn't necessary when using a dataadapter because it opens and closes for you
DataReader code full of magic numbers - GetString(7), hmmm.. was that the time in or time out? GetInt(4) - was it the age? The year? Here we get rid of all the datareader GetXX calls with their column ordinals and fill a DataTable (something like a 2D array) with rows that can be indexed by string names. It's still not as good as it can be (strongly typed DataTables are better) but it's a huge leap better than filling code with magic numbers, and working with everything in the most obscure, weakly typed way possible
Awkward time handling - it's gone in favour of Date parsing, because pulling strings to bits number by number, converting them to int, multiplying them by seconds and hours so they can be manipulated is tedious and hard to read - do away with it all by parsing these strings to the data types that they should have been stored as in the first place; you need to record the date and times that things happen at. Try your best to get that DB converted so these things are stored properly, and until then convert your strings to DateTime
Diffing dates using seconds: utilising TimeSpan calculations means no need to convert things to seconds, do crude math, drop all notions of time zones, or daylight savings changes etc; by using dates subtracted from each other you get a time period between those dates that takes things like daylight saving clock changes into account. Or even the ability to have one date that is tomorrow, or X days into the future. Might not matter for this app, but one day it could..
If you have MySQL 8 you can do the regex replace in the DB. Could even get the DB to diff and sum the dates.. We can't really make any recommendations on this point though because we don't know the column names
I added a function to my application recently that reads a date from a downloaded file and finds the difference in days between current date and the date from the file. When done, it is displayed in a label in one of my forums.
There is an exception: if the string in the file equals "Lifetime", it should not process it as a date and follow alternate logic. But when I try to check if the string is "Lifetime", it does not return true, even if the string = "Lifetime".
EDIT: I fixed the FormatException with help from Nisarg. Now, my labels aren't changing to the values. This is the problem.
EDIT2: I feel stupid. I found out that I was initiating Main twice in one function, then using main1 to switch between forms and main to set the labels.
This is why the labels weren't working right. Thanks Nisarg and all other contributors.
Code example:
string subScript = File.ReadAllText(Path.GetTempPath() + txtUsername.Text + ".txt");
Main main = new Main();
double dSubLeft;
main.dateLabel.Text = subScript;
if (subScript == "Lifetime") // it bypasses this, apparently blank
{
main.daysLeftLabel.Text = "Expires: Never";
}
if (subScript != "Lifetime") //Goes here and throws error saying subScript is not valid DateTime
{
dSubLeft = Math.Round(Convert.ToDouble(Convert.ToString(((Convert.ToDateTime(subScript)) - DateTime.Now).TotalDays)));
string sSubLeft = Convert.ToString(dSubLeft);
main.daysLeftLabel.Text = "Expires: " + sSubLeft + " Days";
}
While using files you often get trailing blank spaces or newline characters. Try trimming the string before comparing it to Lifetime:
subScript = subScript.Trim().Trim(Environment.NewLine.ToCharArray());
Another (less likely) problem could be with the comparison itself. In C# the comparison in case-sensitive. So if you're comparing lifetime with Lifetime they are considered unequal. You should rather use case-insensitive comparison:
if(string.Equals(subScript, "Lifetime", StringComparer.OrdinalIgnoreCase))
OR
if(subScript.ToLower() == "lifetime")
You could also check if the subScript you are getting from the file is a valid date or not using DateTime.TryParse.
string subScript = File.ReadAllText(Path.GetTempPath() + txtUsername.Text + ".txt");
Main main = new Main();
double dSubLeft;
main.dateLabel.Text = subScript;
DateTime subScriptDate;
if(!DateTime.TryParse(subScript, out subScriptDate))
{
main.daysLeftLabel.Text = "Expires: Never";
}
else //Goes here and throws error saying subScript is not valid DateTime
{
dSubLeft = Math.Round(Convert.ToDouble(Convert.ToString((subScriptDate - DateTime.Now).TotalDays)));
string sSubLeft = Convert.ToString(dSubLeft);
main.daysLeftLabel.Text = "Expires: " + sSubLeft + " Days";
}
I think it is because main is the starting point of a program in C#, make another methodname if you don´t want it to reset things from where the program is supposed to start from
That is my guess only, make a breakpoint in the beginning of your code and check through what info you get from each row in the code
Almost certainly, the actual content of the string is not actually the string "Lifetime". Probably because of white-space on either side. Try trimming.
Relevant edit:
if (subscript.Trim() == "Lifetime")
{
main.daysLeftLabel.Text = "Expires: Never";
}
else // don't retest for the opposite condition
{
...
As you can see, this thing is awfully fragile, because the string could still be many things that aren't a valid DateTime. Smells like homework, but there you go...
i think you should use
if(string.Equals(subScript, "Lifetime", StringComparer.OrdinalIgnoreCase))
{
//statement
}
else
{
//statement
}
I'm trying to save a set of records in my desktop c# application and it appears to stop since one of the values was in the incorrect format.
Before saving, the system goes through these computations:
private void ComputeTotalWeight()
{
double TotalWeight;
TotalWeight = ((Convert.ToInt32(txtSmall.Text)) + (Convert.ToInt32(txtMedium.Text)) + (Convert.ToInt32(txtLarge.Text)) +
(Convert.ToInt32(txtExtralarge.Text))) * .285;
txtTotalweight.Text = String.Format("{0:#,##0}", TotalWeight);
}
private void ComputeTagsCollars()
{
int TagsCollars;
TagsCollars = Convert.ToInt32(txtSmall.Text) + Convert.ToInt32(txtMedium.Text)
+ Convert.ToInt32(txtLarge.Text) + Convert.ToInt32(txtExtralarge.Text);
txtTags.Text = String.Format("{0:#,##0}", TagsCollars);
txtCollars.Text = String.Format("{0:#,##0}", TagsCollars);
}
But once I save, it seems to be having a problem with the GrandTotal computation:
I suspect the error come from this computation:
private void ComputeGrandTotal()
{
double GrandTotal;
GrandTotal = (((Convert.ToInt32(txtSmall.Text) + Convert.ToInt32(txtMedium.Text) + Convert.ToInt32(txtLarge.Text) +
Convert.ToInt32(txtExtralarge.Text)) * .285) * 315);
double TagsCollars;
TagsCollars = Convert.ToInt32(txtSmall.Text) + Convert.ToInt32(txtMedium.Text) + Convert.ToInt32(txtLarge.Text) + Convert.ToInt32(txtExtralarge.Text);
txtTags.Text = String.Format("{0:#,##0}", TagsCollars);
txtCollars.Text = String.Format("{0:#,##0}", TagsCollars);
lblGrandtotal.Text = String.Format("{0:#,###,##0}", (GrandTotal + TagsCollars + TagsCollars));
}
I've tried commenting out all GrandTotal related values and functions, and the records begin to save with no problem. Here's a copy of my save function:
private void InsertNewRecord()
{
SqlCommand cmdInsert = new SqlCommand();
cmdInsert.Connection = cn;
cmdInsert.CommandType = CommandType.Text;
//cmdInsert.CommandType = CommandType.StoredProcedure;
cmdInsert.Parameters.AddWithValue("#QtySmall", Convert.ToInt32(txtSmall.Text));
cmdInsert.Parameters.AddWithValue("#QtyMedium", Convert.ToInt32(txtMedium.Text));
cmdInsert.Parameters.AddWithValue("#QtyLarge", Convert.ToInt32(txtLarge.Text));
cmdInsert.Parameters.AddWithValue("#QtyExtralarge", Convert.ToInt32(txtExtralarge.Text));
cmdInsert.Parameters.AddWithValue("#QtyTags", Convert.ToInt32(txtTags.Text));
cmdInsert.Parameters.AddWithValue("#QtyCollars", Convert.ToInt32(txtCollars.Text));
cmdInsert.Parameters.AddWithValue("#TotalWeight", Convert.ToInt32(txtTotalweight.Text));
cmdInsert.Parameters.AddWithValue("#NoWorkers", Convert.ToInt32(txtWorkersno.Text));
cmdInsert.Parameters.AddWithValue("#NoMachines", Convert.ToInt32(txtMachinesno.Text));
cmdInsert.Parameters.AddWithValue("#BomStatus", SqlDbType.VarChar).Value = txtStatus.SelectedItem.ToString();
cmdInsert.Parameters.AddWithValue("#StartDate", SqlDbType.DateTime).Value = dtpStart.Value;
cmdInsert.Parameters.AddWithValue("#EndDate", SqlDbType.DateTime).Value = dtpEnd.Value;
cmdInsert.Parameters.AddWithValue("#GrandTotal", Convert.ToInt32(lblGrandtotal.Text));
cmdInsert.CommandText = " INSERT INTO BillOfMaterials2 " + " (QtySmall, QtyMedium, QtyLarge, QtyExtralarge, QtyTags, QtyCollars, TotalWeight, NoWorkers, NoMachines, BomStatus, StartDate, EndDate, GrandTotal) VALUES (" + "#QtySmall, #QtyMedium, #QtyLarge, #QtyExtralarge, #QtyTags, #QtyCollars, #TotalWeight, #NoWorkers, #NoMachines, #BomStatus, #StartDate, #EndDate, #GrandTotal)";
//cmdInsert.CommandText = "spInsertBom";
cmdInsert.ExecuteNonQuery();
}
Any help would be much appreciated.
1st I would not attempt converting a textbox.text value to Int32 using convert; better to use
Int32 myint = 0;
Int32.TryParse(textbox.text, out myint) ;
This ensures that the text can be converted to an integer and if not you get 0 as a returned out value.
Then in your save method - your #GrandTotal parameter is trying to save to what datatype ? - what is the type in your database ?? do they match - if not you will get a format exception your data (Type) is not the same Format (type) as the column type.
The op does not have a valid number in the text box he has this:
lblGrandtotal.Text = String.Format("{0:#,###,##0}",
(GrandTotal + TagsCollars + TagsCollars));
This is why the code where he sets the parameter value = lblGrandtotal.Text it is not a number it has formatting commas etc.. he needs to remove those to make it work, using Int.TryParse would easily reveal this.
its starts here - first you are putting decimal in your format string with comma.
lblGrandtotal.Text = String.Format("**{0:#,###,##0}**", (GrandTotal + TagsCollars + TagsCollars));
also, later in your code you are storing INT int database, when its actually decimal.
and as mentioned by ken, use tryparse to convert the value from string to ....
There are several issues here some of the other posts touched on but, what really stands out (in my opinion) is you're not validating the input data, which is risky for many reasons, asking for future headaches and causing these issues. Also, there are standard numerical input controls you could use. If there's some reason you can't use them though, you should be validating the input and, if the data is not valid, handle it. Below is a quick way to validate and then handle invalid inputs.
private void ComputeGrandTotal()
{
//Since there are values that need to be validated and converted to integers for use in two calculations...
int smll, mdm, lg, xl;
//Validate the inputs can be converted and set the appropriate variable values at the same time
if (Int32.TryParse(txtSmall.Text, out smll) //using TryParse sets the integer variable values only if they can successfully be converted
&& Int32.TryParse(txtMedium.Text, out mdm)
&& Int32.TryParse(txtLarge.Text, out lg)
&& Int32.TryParse(txtExtralarge.Text, out xl)
)
{
int ttl = smll + mdm + lg + xl;
double GrandTotal, TagsCollars;
TagsCollars = ttl;
GrandTotal = TagsCollars * .285 * 315;
txtTags.Text = $"{TagsCollars:#,##0}"; //Resharper suggested simplification of String.Format("{0:#,##0}", TagsCollars)....I believe ReSharper
txtCollars.Text = $"{TagsCollars:#,##0}";
lblGrandtotal.Text = $"{(GrandTotal + TagsCollars + TagsCollars):#,###,##0}";
}
}
This will get the job done but it's pretty inflexible. Each input has to successfully convert to an integer or this will fail. A better, more time consuming approach would be something like this:
int smll;//, mdm, lg, xl;
try
{
smll = Convert.ToInt32(txtSmall.Text);
}
catch (FormatException)
{
smll = 0;
//txtSmall.Text value can't be converted to an integer
}
catch (Exception)
{
//some other issue occurred and you're probably better off just exiting entirely
return;
}
There are more flexible approaches out there, such as using number styles and such but, their flexibility comes at the price of you having to be more aware of the impact of what and how you're coding. Sometimes it's just safer to train your customers than write code you're not confident with.
You are trying to parse an integer in lblGrantotal.Text, but you are getting a FormatException, which means the text in lblGranTotal isn't recognized as a number. Maybe you are using comma , instead of point . as decimal separator, or something like that.
I have two columns in my table i-e Working Hours and Extra Hours for employee attendance and total time that employee has to work is nine (9) hours if somebody check in at 9 o ' clock and check out at 11 o ' clock then system automatically calculate his/her working hours and extra hours now in this case working hours will be 2 hours and extra hours will be in negative form e.g -7:00:00 hours because employee leave 7 hours before actual time and i stored this negative value as "varchar" in database for user facilitation to understand either employee worked more from given time or less.Now i need to add these extra hours of employee for creating summary of month but i don't know how to add these negative time span and when i convert it to timeofday format then system cannot convert it due to negative sign.
I calculate sum of working hours after reading it from database as:
wrkhrs=wrkhrs.Add(Convert.ToDateTime(dr["WorkHrs"].ToString()).TimeOfDay);
and i found some code for subtraction as:
TimeSpan exthrs = org_work.Subtract(tot_work);
but if timespan have negative sign then it don't work.
if any body have any idea then kindly share it . thanks in advance.
EDIT:
public Tuple<string,string> Calculate_Hours(int id,DateTime strt, DateTime end)
{
TimeSpan wrkhrs = new TimeSpan(0, 0, 0);
TimeSpan exthrs=new TimeSpan(0,0,0);
//select * from vw_Rept_Attend where UserID ='" + id + "' and convert(date,AtnDate) between '" + strt.Date + "' and '" + end.Date + "'
cmd = new SqlCommand("sp_Calculate_Hours_For_Report", conn);
cmd.CommandType = CommandType.StoredProcedure;
cmd.Parameters.AddWithValue("#id", id);
cmd.Parameters.AddWithValue("#startdate", strt.Date);
cmd.Parameters.AddWithValue("#end", end.Date);
conn.Open();
dr = cmd.ExecuteReader();
while (dr.Read())
{
if (dr["WorkHrs"].ToString().Length>0)
wrkhrs=wrkhrs.Add(Convert.ToDateTime(dr["WorkHrs"].ToString()).TimeOfDay);
if (!dr["ExtraHrs"].ToString().Contains("-") && dr["ExtraHrs"].ToString().Length > 0)
{
exthrs = exthrs.Add(Convert.ToDateTime(dr["ExtraHrs"].ToString()).TimeOfDay);
}
else if (dr["ExtraHrs"].ToString().Contains("-") && dr["ExtraHrs"].ToString().Length > 0)
{
string ext = dr["ExtraHrs"].ToString().Substring(dr["ExtraHrs"].ToString().LastIndexOf("-") +1);
exthrs = exthrs.Subtract(Convert.ToDateTime(ext).TimeOfDay);
}
}
conn.Close();
dr.Close();
return new Tuple<string, string>(string.Format("{0:00}:{1:00}:{2:00}", (int)TimeSpan.Parse(wrkhrs.ToString()).TotalHours, Math.Abs((int)TimeSpan.Parse(wrkhrs.ToString()).Minutes), Math.Abs((int)TimeSpan.Parse(wrkhrs.ToString()).Seconds)), string.Format("{0:00}:{1:00}:{2:00}", (int)TimeSpan.Parse(exthrs.ToString()).TotalHours, Math.Abs((int)TimeSpan.Parse(exthrs.ToString()).Minutes), Math.Abs((int)TimeSpan.Parse(exthrs.ToString()).Seconds)));
}
and called out put of above function as:
var mytuple = Calculate_Hours(id,Convert.ToDateTime(dtStart.Text), Convert.ToDateTime(dtEnd.Text));
string tot_workHrs= mytuple.Item1;
string tot_ExtHrs= mytuple.Item2;
above is my logic that i retrieve my correct output, if someone has any question then please feel free to ask me by creating new comment on this post.
hope now this will be helpful for all....
1.
Use TimeSpan.Duration():
https://msdn.microsoft.com/en-us/library/system.timespan.duration(v=vs.110).aspx
"Returns a new TimeSpan object whose value is the absolute value of
the current TimeSpan object"
2.
Or some code from HERE:
static string ToHMString(TimeSpan timespan) {
if (timespan.Ticks < 0) return "-" + ToHMString(timespan.Negate());
return timespan.TotalHours.ToString("#0") + ":" + timespan.Minutes.ToString("00");
}
Console.WriteLine(ToHMString(TimeSpan.FromHours(3))); //Prints "3:00"
Console.WriteLine(ToHMString(TimeSpan.FromHours(-27.75))); //Prints "-28:45"
First of all it is a bad idea to store a time/duration value as string in the database.
Second the .Net TimeSpan structure is perfectly able to represent negative durations and calculate with these correctly.
Suggestions:
Store your negative duration as a time/duration value in the databese. If your database has no duration type which supports negative values add a boolean "This value is negative"
In your C# code use TimeSpan and the usual operators: +and -
Does this do what you need?
string[] sample = new string[] { "2.1", "-7.0", "1.0" };
TimeSpan total =
sample
.Select(s => TimeSpan.FromHours(double.Parse(s)))
.Aggregate((ts0, ts1) => ts0.Add(ts1));
The total I get is -03:54:00 as a TimeSpan.
I am working on a C# project and I am facing an issue. The program allows the user to connect to a MySQL database and retrieve information from each selected table and write the data out to a file. The problem is because I have no idea what the schema is going to be like or what values its going to contain.
If the timestamp column contains the date 0000-00-00 00:00:00 I get the conversion error and no matter what I try it never works. I've tried converting to a string I've tried converting to a DateTime but I always get the error.
Below is how I am currently trying to get the data:
using (ConnectMySQLDB db = new ConnectMySQLDB(databaseSettings))
{
string query = string.Format("SELECT * FROM {0}.{1}", database, table);
Console.WriteLine("Query: {0}", query);
using (MySqlCommand cmd = new MySqlCommand(query, db.conn))
{
using (MySqlDataReader reader = cmd.ExecuteReader())
{
int i = 1;
while (reader.Read())
{
Console.WriteLine("ID: {0}", i);
fieldsAndValues = new Dictionary<string, string>();
foreach (ColumnDataTypes fieldAndType in fieldsAndTypes)
{
Console.WriteLine("Column: {0} Type: {1}", fieldAndType.field, fieldAndType.dataType);
string formattedValue = "";
if (fieldAndType.dataType == "timestamp")
{
DateTime date = DateTime.Parse(reader.GetDateTime(fieldAndType.field).ToString());
formattedValue = date.ToString("yyyyMMdd");
}
else
{
formattedValue = getDBFormattedValue(reader.GetString(fieldAndType.field), fieldAndType.dataType);
fieldsAndValues.Add(fieldAndType.field, formattedValue);
}
}
rows.Add(fieldsAndValues);
i++;
}
}
}
}
I also have added the allow zero date and convertzerodate to null option in the connector string as follows:
connString = "server=" + server + ";uid=" + username + ";pwd=" + password + ";port=" + port + ";Allow Zero Datetime=true;zeroDateTimeBehavior=convertToNull;Convert Zero Datetime=true";
Looking at this documentation, it looks like you're specifying two contradictory options (AllowZeroDateTime=true and ConvertZeroDateTime=true) and one which appears not to be listed (ZeroDateTimeBehavior=ConvertToNull).
I suggest that unless you have actual data which is DateTime.MinValue which you don't want to mix up with the "zero" value, you just specify ConvertZeroDateTime=true and detect if the result is DateTime.MinValue. You definitely shouldn't call reader.GetDateTime(), then convert the result to a string, and then back to a DateTime - you should avoid string conversions as far as you can, as they can mess things up for you pretty easily.
It's not really clear what string value you want for these "zero" values, but you should be able to special-case them with DateTime.MinValue fairly easily. Personally I'd actually try to keep the data in its "native" form as much as possible rather than converting everything to strings, but that's a different battle.