This will be a noobish question but I am currently working on a program that will take in a user input in the format of DD/MM/YYYY and the output it in the format 1st of May 2017, for example.
But whenever the use string.substring (UserInput.substring in my case) it does not separate the values correctly. For example, when I input the date as 21/05/2001 it displays 215 2001. I have no idea why this is happening.
Im sorry as this is very noobish but I am new to using .substring and I'm sure the problem will seem obvious when someone points it out xD
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace DateProgram
{
class Program
{
static void Main(string[] args)
{
/// Define Varibles
string UserIntput;
int Day;
int Month;
int year;
///Gathering UserInput
Console.Write("Please enter the date in the format dd/mm/yyyy");
UserIntput = Console.ReadLine();
///Validations
try
{
while(UserIntput.Substring(2,1) != "/" || UserIntput.Substring(5,1) != "/" || UserIntput.Length != 10)
{
Console.WriteLine("Invalid Input");
Console.Write("Please enter the date in the format dd/mm/yyyy");
UserIntput = Console.ReadLine();
}
}
catch
{
Console.WriteLine("Invalid Input");
}
/// Defining to Variables
Day = Convert.ToInt32(UserIntput.Substring(0, 2));
Month = Convert.ToInt32(UserIntput.Substring(3, 2));
year = Convert.ToInt32(UserIntput.Substring(6, 4));
Console.WriteLine(Day + "" + Month + " " + year);
Console.ReadLine();
}
}
}
Pass your user input string in to a System.Convert.ToDateTime method:
DateTime dt = Convert.ToDateTime(UserIntput);
Then, if you would like to change the format of how it is presented, use one of the DateTime.ToString() overloads to convert it to the format you want. (Search for ToString() on this page)
It might look something like this:
dt.ToString("MM-dd-yyyy", System.Globalization.CultureInfo.InvariantCulture);
You'll also want to review this page: Custom Date and Time Format Strings
Use ParseExact like this:
using System;
public class Program
{
public static void Main()
{
DateTime? dt = null;
do
{
Console.WriteLine("Input date: (dd/MM/yyyy)");
var input = Console.ReadLine();
try
{
dt = DateTime.ParseExact(input, "dd/MM/yyyy", System.Globalization.CultureInfo.InvariantCulture);
}
catch(Exception ex)
{
Console.WriteLine(ex.Message);
}
} while (!dt.HasValue);
Console.WriteLine(dt.Value.ToString("F"));
var myDate = dt.Value;
// access the single fields from the parsed object
Console.WriteLine(myDate.Day);
Console.WriteLine(myDate.Month);
Console.WriteLine(myDate.DayOfWeek);
Console.WriteLine(myDate.Year);
}
}
See https://dotnetfiddle.net/TeYSF7
In addition to the "custom" link for DateTime-Formatting (see BobbyA's answer), consider these which come by default: standard-date-and-time-format-strings
Using string.Split(..) - although why if DateTime comes with valid ways to parse.
var parts = "22/12/2012".Split(new []{'/'}, StringSplitOptions.RemoveEmptyEntries);
if (parts.Length == 3)
{
var day = int.Parse(parts[0]); // will crash if not an int - use .TryParse(...) or handle error
var month = int.Parse(parts[1]); // will crash if not an int
var year = int.Parse(parts[2]); // will crash if not an int
var date = new DateTime(day,month,year)) // will crash if f.e. 45.24.788
}
else
{
// invalid input
}
Try parsing date and time with a help of DateTime.TryParseExact which has been specially designed for such tasks:
using System.Globalization;
...
DateTime userDate;
// Gathering UserInput (just one simple loop)
do {
Console.WriteLine("Please enter the date in the format dd/mm/yyyy");
}
while (!DateTime.TryParseExact(Console.ReadLine(),
"d/m/yyyy", // be nice, let 21.5.2017 be valid; please, do not inist on 21.05.2017
CultureInfo.InvariantCulture,
DateTimeStyles.AssumeLocal,
out userDate));
// If you insist on these local variables:
int day = userDate.Day;
int month = userDate.Month;
int year = userDate.Year;
// But I suggest formatting or string interpolation:
Console.WriteLine($"{userDate:dd MM yyyy}");
Assuming you want to keep your current approach (instead of using any of the built-in functions provided in the other answers), your problem is just a typo.
Change this:
Console.WriteLine(Day + "" + Month + " " + year);
To this:
Console.WriteLine(Day + " " + Month + " " + year); //Notice the space
In the future, you can avoid this sort of problem by using a constant:
const string space = " ";
Console.WriteLine(Day + space + Month + space + year);
Related
By Input i mean Console.ReadLine() and the way it got changed.
I tried to make a code that could count the days that the User inputed left in the same Year.
After that it should it should loop through the for loop.
This is what it should do.
The Output should be: The difference between the two Inputs, the amount of days it takes to end the year with the first Input in mind subtract that with the total amount and if it is more then 360 it should output the amount and subtract it with 360 so long until the it is under 360.
My Current Output is: 0 Days when numberOfDays is Outputed and when NumberOfDays2 is outputed the Output is 363.
My Problem is that i dont know what exactly the problem is in my Code.
It would be a great help if someone could explain to me where the Problem is or what the root of the Problem is.
Rightnow im very confused do to the comparison with my other code i made where parts like (.TotalDays) perfectly worked.
I would like to know why it doesnt work because in theory it should work.
internal class Program
{
static void Main(string[] args)
{
//Input and Visual
Console.WriteLine("write here Beginning");
Console.Write("Day: ");
string FirstDay = Console.ReadLine();
Console.Write("Month:");
string StillFirstDay = Console.ReadLine();
Console.Write("Year:");
string Still_FirstDay = Console.ReadLine();
Console.Clear();
Console.WriteLine("Beginn: " + FirstDay + "." + StillFirstDay + "." + Still_FirstDay);
Console.WriteLine("");
Console.WriteLine("write here End ");
Console.Write("Day: ");
string LastDay = Console.ReadLine();
Console.Write("Monat:");
string StillLastDay = Console.ReadLine();
Console.Write("Jahr:");
string Still_LastDay = Console.ReadLine();
//Prepare
int input = 0;
int IFirstDay = 1;
int IStillFirstDay = 1;
int IStill_FirstDay = 1;
int ILastDay = 1;
int IStillLastDay = 1;
int IStill_LastDay = 1;
JustforConversion(FirstDay, input, IFirstDay);
JustforConversion(StillFirstDay, input, IStillFirstDay);
JustforConversion(Still_FirstDay, input, IStill_FirstDay);
JustforConversion(LastDay, input, ILastDay);
JustforConversion(StillLastDay, input, IStillLastDay);
JustforConversion(Still_LastDay, input, IStill_LastDay);
DateTime date1 = new DateTime(IStill_LastDay, IStillLastDay, ILastDay);
DateTime date2 = new DateTime(IStill_FirstDay, IStillFirstDay, IFirstDay);
var numberOfDays = (date2 - date1).TotalDays;
Console.WriteLine(numberOfDays);
int Year = IStill_FirstDay - IStill_LastDay;
DateTime date3 = new DateTime(IStillFirstDay, 12, 30);
var numberOfDays1 = (date3 - date2).Days;
Console.WriteLine(numberOfDays1);
var numberOfDays2 = numberOfDays - numberOfDays1;
Console.WriteLine("In Year 1 there were " +numberOfDays1+" Days.");
for (int i = 2; i <= Year; i++)
{
if (numberOfDays2 > 360)
{
Console.WriteLine("In Year " + i + " there were " + numberOfDays2 + " Days.");
numberOfDays2 -= 360;
}
else
{
Console.WriteLine(numberOfDays2);
break;
}
}
Console.ReadKey();
}
static void JustforConversion(string Converted,int Zero,int Complete_Convert)
{
while (int.TryParse(Converted, out Zero))
{
Complete_Convert = Convert.ToInt32(Converted);
break;
}
}
}
}
Your JustforConversion() method has so many things wrong with it, but the biggest problem is that it doesn't actually "return" anything. ints are passed "by value", which means a copy is made; the original variable is NOT changed after the call to JustforConversion().
It looks like you were expecting the "Ixxx" variables to have valid integers in them after the calls. You'd need to declare that parameter as an out parameter for this to work:
static void Main(string[] args)
{
string FirstDay = "10";
int IFirstDay = 1;
Console.WriteLine("Before JustforConversion():");
Console.WriteLine("IFirstDay = " + IFirstDay);
JustforConversion(FirstDay, out IFirstDay);
Console.WriteLine("After JustforConversion():");
Console.WriteLine("IFirstDay = " + IFirstDay);
}
static void JustforConversion(string Converted, out int IConverted)
{
IConverted = int.Parse(Converted);
}
Output:
Before JustforConversion():
IFirstDay = 1
After JustforConversion():
IFirstDay = 10
I'm trying to add days or month to a datetime. What determines rather it should add days or month to the datetime is what dayOrMonth ends with. So for example if dayOrMonth ends with MM it should add month, if it ends with DD it should add days.
dayOrMonth could look like this "90DD" (should add 90 days) and "90MM" should add 90 month.
I'm thinking about creating an extension method of some kind, but I'm struggling abit with the approach to this, as adding more if statements is not an option.
//... Set payment dates.
string dayOrMonth;
for (int x = 0; x < installmentDates.Count; x++)
{
if (installmentDates.Count > 0)
{
installmentdDateRow[colName] = installmentdDateRow[colName] + Convert.ToDateTime(installmentDates[x]).ToString("dd'-'MM'-'yyyy") + "\n";
//... Future payment dates.
int futurePaymentColumn = installmentdFuturePayments.Table.Columns.IndexOf(colName);
if (colName == "1. rate" && installmentDates.Count - 1 == x)
{
installmentdFuturePayments[futurePaymentColumn + 1] = installmentdFuturePayments[futurePaymentColumn + 1] + Convert.ToDateTime(installmentDates[x]).AddMonths(3).ToString("dd'-'MM'-'yyyy") + "\n";
}
if (colName == "2. rate" && installmentDates.Count - 1 == x && Functions.GetProductInfo(unit.Key.ToString().Split('-')[0])[9] != "€ 0,00")
{
installmentdFuturePayments[futurePaymentColumn + 1] = installmentdFuturePayments[futurePaymentColumn + 1] + Convert.ToDateTime(installmentDates[x]).AddMonths(3).ToString("dd'-'MM'-'yyyy") + "\n";
}
}
}
You have described an input string composed of two parts:
An integer magnitude to apply to some operation
A two character string defining the operation to use
As such, you know there should always be at least three characters. You also know the trailing two characters define the operation, so you can use Substring to separate those characters from the rest of the string.
An extension method is a great idea. It should include tests to help enforce the format of the input string, and make it easy to parse the numeric component.
public static DateTime ApplyInput(this DateTime dt, string input)
{
if (input == null)
{
throw new ArgumentNullException(nameof(input), "The input string must not be null.");
}
if (input.Length < 3)
{
throw new ArgumentException("The input string is too short to include both a number and an operation.", nameof(input));
}
string numberChars = input.Substring(0, input.Length - 2);
if (!int.TryParse(numberChars, out int number))
{
throw new ArgumentException("The start of the input string must be an integer.", nameof(input));
}
string endingChars = input.Substring(input.Length - 2);
switch (endingChars.ToUpperInvariant())
{
case "MM":
return dt.AddMonths(number);
case "DD":
return dt.AddDays(number);
default:
throw new ArgumentException($"The characters {endingChars} were not recognized as a valid operation.", nameof(input));
}
}
This approach will perform better than using RegEx, Contains, or Replace. It is also extensible by adding more case statement to the switch.
Note that .ToUpperInvariant() makes the operation characters case-insensitive so you can pass mm or dd if you like. If you don't wan't that behavior, then simply remove .ToUpperInvariant().
Using StackOverflow - Seperating characters and numbers
You can use a regular expression to seperate the numbers from the characters in a given string like so:
Regex re = new Regex(#"([a-zA-Z]+)(\d+)");
Match result = re.Match(input);
string alphaPart = result.Groups[1].Value;
string numberPart = result.Groups[2].Value;
Then you can create a factory method or a project wide reference where you can use that code snippet to achieve what youre asking:
public DateTime AddDaysOrMonths(string input, DateTime dt)
{
Regex re = new Regex(#"([a-zA-Z]+)(\d+)");
Match result = re.Match(input);
string alphaPart = result.Groups[1].Value;
string numberPart = result.Groups[2].Value;
if(alphaPart == "DD")
{
int days;
if(Integer.TryParse(numberPart,out days) == true)
{
dt.AddDays(days)
}
}
else if (alphaPart == "MM")
{
int months;
if(Integer.TryParse(numberPart,out months) == true)
{
dt.AddMonths(months);
}
}
return dt;
}
Ofcourse, you should implement more extenstive error/null checking and better string comparison but this should be enough to get you going in the right direction.
I solved my problem by creating this extension method
public static DateTime test1(this DateTime d, string inputType)
{
if (inputType.Contains("DD"))
{
d = d.AddDays(Convert.ToInt32(inputType.Replace("DD", "")));
}
if (inputType.Contains("MM"))
{
d = d.AddMonths(Convert.ToInt32(inputType.Replace("MM", "")));
}
return d;
}
So I have a program I use that I have become very intrigued by how they force their formatting of a date in a field when input. For example, if I put in "10217", the system would automatically force the field to become 10/02/2017. However, if I put in 1117, then nothing happens as it could be 01/01/2017, 11/17/??, or some other of many combinations. Does anyone know how this forced formatting might be being achieved regarding the logic?
Additionally, you can put in a date in the same field formatted as 10.2.17 and it would reformat to 10/2/2017. As well, if you input 1.1.17, it would reformat to 1/1/2017. Lastly, you can do the same thing of putting in the slashes and it will reformat the respective date format. So if I put in 10/2/17, it would reformat to 10/2/2017. Same this with typing 1/1/17 will reformat to 1/1/2017.
I've looked at the following link, but am not seeing anything that could be used to do this kind of logic. (Granted I could just be blatantly missing it.)
https://learn.microsoft.com/en-us/dotnet/standard/base-types/custom-date-and-time-format-strings
As well, I have seen this example surrounding a regex, but I am not familiar with this process.
Validating a date format string in c#
I understand this is a lot, but this all revolves around the date forced formatting logic. I am really not sure what logic to use to achieve what I want or what logic to chain together to achieve what I am looking for. I greatly appreciate all of the input.
I think to approach this problem it may be necessary to see what they are using to parse the input of the user. If they are using DateTime.Parse then it will throw an exception when the string being parsed is ambiguous.
Of course, a programmer could always create their own way of parsing the input in the field. Though, typically a programmer isn't that enthusiastic about dealing with the ambiguous cases when parsing information. So let's assume they are working with a DateTime.Parse method for simplicity sake.
I created the following program to allow you to see when the parser sees something as ambiguous. The output of the program is shown in this picture:
The code demonstrating DateTime.Parse:
static void Main(string[] args)
{
string input = "";
while(input != "exit" || input != "Exit")
{
Console.Write("Input: ");
input = Console.ReadLine();
string inputDate = input;
//try to parse it
try
{
DateTime date = DateTime.Parse(inputDate);
Console.WriteLine(date+"\n");
}
catch
{
//Exceptions. String not valid because ambiguity
Console.WriteLine("Ambiguous.\n");
//In here can also perform other logic, of course
}
}
}
In order to convert the DateTime back to a string you can do something similar to:
try
{
DateTime date = DateTime.Parse(inputDate);
Console.WriteLine(date+"\n");
string month = date.Month.ToString();
string day = date.Day.ToString();
string year = date.Year.ToString();
string resultingString = month + " " + day + " " + year ;
Console.WriteLine(resultingString);
}
catch(Exception e)
{
//Exceptions. String not valid because ambiguity
Console.WriteLine("Ambiguous");
}
You can even make your own parser with this information in this fashion so you can acheive a result for a date entered that is 3 characters long:
static void Main(string[] args)
{
string input = "";
while(input != "exit" || input != "Exit")
{
Console.Write("Input: ");
input = Console.ReadLine();
string inputDate = input;
try
{
DateTime date = DateTime.Parse(inputDate);
Console.WriteLine(date+"\n");
string month = date.Month.ToString();
string day = date.Day.ToString();
string year = date.Year.ToString();
string resultingString = month + " " + day + " " + year;
//string resultingString = month + "/" + day + "/" + year;
Console.WriteLine(resultingString);
}
catch(Exception e)
{
//Exceptions. String not valid because ambiguity
try
{
Console.WriteLine( myParser(inputDate) );
}
catch
{
Console.WriteLine("Ambiguous");
}
//Console.WriteLine("Ambiguous.\n");
//In here can also perform other logic, of course
}
}
}
static string myParser(string input)
{
string month,day,year,date;
switch (input.Length)
{
//In the case that it's 1 character in length
case 1:
return "Ambiguous.";
case 2:
return "Ambiguous.";
//did user mean #/#/200#? hopefully not #/#/199#...
case 3:
month = input.Substring(0, 1);
day = input.Substring(1, 1);
year = input.Substring(2, 1);
date = month + " " + day + " " + year;
return date;
//did user mean # # 20##
//or # ## 200#
//or ## # 200#
case 4:
return "Ambiguous";
//user probably means ## # ##
case 5:
return "Ambiguous";
case 6:
return "Ambiguous";
default:
return "Ambiguous";
}
}
Similarly, if you want to get the date back to a slash (/) seperated format in the form of a string without the minutes and hours and such..
case 3:
month = input.Substring(0, 1);
day = input.Substring(1, 1);
year = input.Substring(2, 1);
date = month + " " + day + " " + year;
DateTime dateTimeObj = DateTime.Parse(date);
month = dateTimeObj.Month.ToString();
day = dateTimeObj.Day.ToString();
year = dateTimeObj.Year.ToString();
string resultingString = month + "/" + day + "/" + year;
return resultingString;
I'm having problems with error: input string was not in a correct format. I'm trying to convert curency in datagrid. At point where I get error (this is where I set value to value variable) text variable haves value 22.22 so I don't know what is wrong with format.
public void valute()
{
int rowCount = dataGridView1.RowCount;
decimal value = 0;
for (int i = 0; i < rowCount; i++)
{
string text = dataGridView1.Rows[i].Cells[3].Value.ToString();
if (evro_check.Checked)
dataGridView1.Rows[i].Cells[3].Value = text + " €";
else if (dolar_check.Checked)
{
value = Decimal.Parse(text.Replace(',', '.'), CultureInfo.InvariantCulture);
dataGridView1.Rows[i].Cells[3].Value = value.ToString() + " $";
}
else
{
dataGridView1.Rows[i].Cells[3].Value = value + " £";
}
}
}
EDIT: Right now I'm just adding curency sign and later I'll also change € to $ and thats way I'm using additional variable (value) and not using text for other 2 currencys.
The best option you have is to use Tryparse over Parse
TryParse
This overload differs from the Decimal.Parse(String) method by returning a Boolean value that indicates whether the parse operation succeeded instead of returning the parsed numeric value. It eliminates the need to use exception handling to test for a FormatException in the event that s is invalid and cannot be successfully parsed.
A suggestion to improve the code
string text = dataGridView1.Rows[i].Cells[3].Value.ToString();
Decimal value=0;
if (Decimal.TryParse(text.Replace(',', '.'), out value))
{
//parse success
dataGridView1.Rows[i].Cells[3].Value = value.ToString() + " $"; // put the correct value
}
else {
//parse not success
dataGridView1.Rows[i].Cells[3].Value ="- $"; // Put something which allow you to identify the issue.
}
This will allow you to identify where you have wrongly formatted values in data grid.
Be careful with cultures.
For example in the UK this "10,000.10" is 10 thousand and 1/10 of your currency, while in Germany the format would be the other way around: "10.000,10".
What you do is replacing all "," with an ".". Unless you changed the current culture of your application to a format where this makes sense, then this will obviously end up with a FormatException.
You should set the CultureInfo to the culture which you are targeting.
https://msdn.microsoft.com/en-US/library/b28bx3bh%28v=vs.80%29.aspx
https://msdn.microsoft.com/en-us/library/bz9tc508%28v=vs.140%29.aspx
Also, it would be better to use a format provider, which will format you a correct monetary string according to the specified culture:
decimal value = 10000;
value.ToString("C", CultureInfo.InvariantCulture);
// Output : ¤10,000.00
value.ToString("C", CultureInfo.GetCultureInfo("de-DE"));
// Output : 10.000,00 €
value.ToString("C", CultureInfo.GetCultureInfo("en-US")).Dump();
// Output: $10,000.00
If you notice, the American format puts the currency symbol at the front, and the German one is at the end. You didn't account for any of these things either.
See: https://msdn.microsoft.com/en-us/library/0b22a4x2%28v=vs.110%29.aspx
try this
public void valute()
{
int rowCount = dataGridView1.RowCount;
decimal value = 0;
for (int i = 0; i < rowCount; i++)
{
string text = dataGridView1.Rows[i].Cells[3].Value.ToString();
if (evro_check.Checked)
dataGridView1.Rows[i].Cells[3].Value = text + " €";
else if (dolar_check.Checked)
{
if (text != "" || text != " ")
{
value = Decimal.Parse(text.Replace(',', '.'), CultureInfo.InvariantCulture);
dataGridView1.Rows[i].Cells[3].Value = value.ToString() + " $";
}
}
else
{
dataGridView1.Rows[i].Cells[3].Value = value + " £";
}
}
}
You can make use of Culture Info class.
public void valute()
{
int rowCount = dataGridView1.RowCount;
decimal value = 0;
for (int i = 0; i < rowCount; i++)
{
string text = dataGridView1.Rows[i].Cells[3].Value.ToString();
if (evro_check.Checked)
dataGridView1.Rows[i].Cells[3].Value = text.ToString("C", CultureInfo.GetCultureInfo("fr")); //€
else if (dolar_check.Checked)
{
value = Decimal.Parse(text.Replace(',', '.'), CultureInfo.InvariantCulture);
dataGridView1.Rows[i].Cells[3].Value = text.ToString("C", CultureInfo.GetCultureInfo("fr-CA")); //$
}
else
{
dataGridView1.Rows[i].Cells[3].Value = text.ToString("C", CultureInfo.GetCultureInfo("en-GB"));
}
}
}
Second Approach
make use of Unicode
public static char HexToChar(string hex)
{
return (char)ushort.Parse(hex, System.Globalization.NumberStyles.HexNumber);
}
\u00A3 is the Pound sign, £
\u20AC is the Euro sign, €.
\u0024 is the dollar sign, $.
How to insert a Symbol (Pound, Euro, Copyright) into a Textbox
I have a small C# program that has a calendar and 7 labels. When I select a date the labels display the days and dates of that week.
The labels are populated using the TimeSpan string what I want to do is format this string so that it only displays the days and dates with out the times.
This is the code I have so far:
private void monthCalendar1_DateSelected(object sender, DateRangeEventArgs e)
{
DateTime dTime = new DateTime();
dTime = monthCalendar1.SelectionStart;
dTime -= new TimeSpan((int)dTime.DayOfWeek, 0, 0, 0 );
for (int i = 1; i < 8; i++)
{
var dt = dTime.AddDays(i);
lb[i].Text = dt.DayOfWeek + " : " + dt.Date;
}
}
You can call dt.Date.ToShortDateString().
You have multiple options.
You can use ToShortDateString() method for the DateTime type
lb[i].Text = dt.DayOfWeek + " : " + dt.Date.ToShortDateString()
or you can provide of a format to the ToString("format") method to specify exactly what you want it to look like.
lb[i].Text = dt.DayOfWeek + " : " + dt.Date.ToString("MM/dd/yyyy");
Try with DateTime.ToShortDateString() method;
Converts the value of the current DateTime object to its equivalent
short date string representation.
DateTime dt = DateTime.Now;
label8.Text = dt.Date.ToShortDateString());
You can learn more details from Custom Date and Time Format Strings