Using C#, I am trying to populate a variable with a known filename + date. The catch is that the date must always be the last day of the previous month. It must also have no slashes or hyphens, and the year must be two digits. For example, if it is now November 27 2015, I need my filename to be: Foobar_103115.txt
As a programmer who still has much to learn, I have written the clunky code below and it does achieve my desired result, even though it will obviously break after the end of this century. My code is written this way because I could not figure out a more direct syntax for getting the date I want, complete with the specified formatting.
My question is this: What would be a more elegant and efficient way of recreating the below code?
I have commented all the code for any novice programmers who might be interested in this. I know the experts I'm asking for help from don't need it.
public void Main()
{
String Filename
DateTime date = DateTime.Today;
var FirstDayOfThisMonth = DateTime.Today.AddDays(-(DateTime.Today.Day - 1)); //Gets the FIRST DAY of each month
var LastDayOfLastMonth = FirstDayOfThisMonth.AddDays(-1); //Subtracts one day from the first day of each month to give you the last day of the previous month
String outputDate = LastDayOfLastMonth.ToShortDateString(); //Reformats a long date string to a shorter one like 01/01/2015
var NewDate = outputDate.Replace("20", ""); //Gives me a two-digit year which will work until the end of the century
var NewDate2 = NewDate.Replace("/", ""); //Replaces the slashes with nothing so the format looks this way: 103115 (instead of 10/31/15)
Filename = "Foobar_" + NewDate2 + ".txt"; //concatenates my newly formatted date to the filename and assigns to the variable
Sounds like you want something more like:
// Warning: you should think about time zones...
DateTime today = DateTime.Today;
DateTime startOfMonth = new DateTime(today.Year, today.Month, 1);
DateTime endOfPreviousMonth = startOfMonth.AddDays(-1);
string filename = string.Format(CultureInfo.InvariantCulture,
"FooBar_{0:MMddyy}.txt", endOfPreviousMonth);
I definitely wouldn't use ToShortDateString here - you want a very specific format, so express it specifically. The results of ToShortDateString will vary based on the current thread's culture.
Also note how my code only evaluates DateTime.Today once - this is a good habit to get into, as otherwise if the clock "ticks" into the next day between two evaluations of DateTime.Today, your original code could give some pretty odd results.
Related
I have to parse date string in C#. The dates are all ensured to start with year, month, day. But I do not know what dividers will be between the 3 parts.
Additionally the date string may also include a time part after the date.
Basically as long as the format has the year first, month second, and day third, I should parse it as a valid date regardless of which dividers are used and whether a time is included. Any other date formats should be rejected as invalid.
I can not figure out how to do this without writing a long if/else.
How do I parse a string into a C# datetime object, given the restrictions mentioned?
You can check the length of the input string is at least 10 characters, and if it is, work out what the separator should be by looking at the 5th character in the string.
Then you can use the separator to construct a format string that you pass to DateTime.TryParseExact() to parse the date. You also have to truncate the date string to 10 characters to ignore any date part at the end.
An example implementation looks like this - it returns null if the date didn't parse; otherwise, it returns the correctly parsed date:
public static DateTime? ParseDateWithUnknownDivider(string dateStr)
{
if (dateStr.Length < 10)
return null;
char divider = dateStr[4];
if (DateTime.TryParseExact(
dateStr.Substring(0, 10),
$"yyyy\\{divider}MM\\{divider}dd",
CultureInfo.InvariantCulture,
DateTimeStyles.None,
out DateTime result))
return result;
return null;
}
Note that this ignores the time part and will always return the time part as 00:00:00. If that's not what you meant, you will need to specify in your question what the time part would look like. For example, would it be separated from the date part by a space? And would it always be hh:mm:ss? And would it be 24hour clock?
try this code
string yourDateTimeString = ....;
string format="yyyy/MM/dd";
var dt = DateTime.ParseExact(yourDateTimeString,format,null,System.Globalization.DateTimeStyles.AssumeLocal);
I want to get the current time in T07:07:45-0500 format.
I have try like this:
DateTime currentDate = DateTime.Now;
String currentTime = currentDate.ToString("'T'HH':'mm':'ssK");
Console.WriteLine("DOB ==> " + dateOfBirth.ToString("yyyy-MM-dd") + currentTime);
But the result is 1986-07-11T07:07:45-05:00
I want result like 1986-07-11T07:07:45-0500
Is there any way to get the current time in T07:07:45-0500 format.
Please help me to resolve my problem.
I don't think the .NET custom date and time format strings allow that format. You could use my Noda Time project easily enough, using DateTimeOffset.Now if you want the system default time zone to be applied. (It can be done explicitly
For example:
var odt = OffsetDateTime.FromDateTimeOffset(DateTimeOffset.Now);
var pattern = OffsetDateTimePattern.CreateWithInvariantCulture(
"yyyy-MM-dd'T'HH:mm:sso<+HH:mm>");
Console.WriteLine(pattern.Format(odt));
As noted in comments, you're currently doing something very odd in terms of combining the values. If you really want to do that, I would personally create an appropriate OffsetDateTime like this:
LocalDate dateOfBirth = ...; // Wherever that comes from
OffsetDateTime now = OffsetDateTime.FromDateTimeOffset(DateTimeOffset.Now);
OffsetDateTime mixture = dateOfBirth.At(now.LocalTime).WithOffset(now.Offset);
var pattern = ...; // as before
Console.WriteLine(pattern.Format(mixture));
That makes it clearer how you're combining the values.
I think the representation of an offset depends on how your CurrentCulture represents UTC Offset value. It might be the formats as -05:00, -0500, or simply -05.
Based on comments, looks like UTC Offset format is hard-coded and it doesn't depends on any culture.
You should clearly find the last index of : character and replace it with empty string. I don't think there is another solution for this in .NET Framework.
DateTime currentDate = DateTime.Now;
String currentTime = currentDate.ToString("'T'HH':'mm':'ssK");
currentTime = currentTime.Remove(currentTime.LastIndexOf(":"), 1);
I am writing a program in c# and I need to do some math with dates. I need to let the user enter a date, calculate the date that is 91 days later, and then find the month right after that. ex: user enters date of 1/15/12, it should add 91 days, 4/15/12, and then return a date of 5/1/12. Unfortunately, I have no idea how to do this and I couldn't find anything that was helpful.
var oldDate = <your_datetime_variable>.AddDays(91);
var newDate = new DateTime(oldDate.Year, oldDate.Month, 1).AddMonths(1);
Since constructing a new DateTime object has been suggested, here is another approach:
DateTime when = <user_supplied_date>;
DateTime future = when.AddDays(91);
when = future.AddDays(-(future.Day - 1)).AddMonths(1);
This is a little cryptic, but results in a one-liner that you could use.
i'm currently working on a little project and i'm stuck with a little problem.
I would like my program to call a method CheckDate on boot.
This method would read in a .txt file to see the last saved date in (yyyy/mm/dd) format.
Then it would compare it with todays date and if it's not the same go on with some instructions.I've read the doc here but can't quite find which method best suites my need.
Question 1: Is there a way to get today's date in (yyyy/mm/dd) format?
Question 2: What's the easiest way to compare Dates in C#?
Thanks in advance.
1. DateTime.Now.ToString("yyyy/MM/dd")
2. DateTime.Parse(input).Date == DateTime.Now.Date
You can get today's date as a string by simply formatting a date.
String today = String.Format("{0: yyyy/MM/dd}", DateTime.Now);
String today = DateTime.Now.ToString("yyyy/MM/dd");
I would advise against using a text file as your means of saving data but if you are going with that system the only thing you would have to do is check to see if the date from the text file matches the date you formatted. Simply comparing formatted strings should do the trick.
if (string a == string b)
You could even put it in one line without having to format stuff separately
if (DateTime.Now.ToString("yyyy/MM/dd").Equals("date pulled from txt file"))
What's the easiest way to compare Dates in C#?
Store them not as text but in a DatteTime.
Compare the variables.
If there is a time in both, compare a.Date == b.Date.
Is there a way to get today's date in (yyyy/mm/dd) format?
Yes. This is wrong, though. PARSE The wrong input and compare the parsed data.
There is a DateTime.Compare method that you could use http://msdn.microsoft.com/en-us/library/system.datetime.compare.aspx - this should also let you use the built-in < and > operators.
By the letter of the question:
1:
DateTime.Now.ToString(#"yyyy\/MM\/dd")
2:
if(d1 < d2)...
if(d2 >= d1)...
etc.
However.
DateTime dt;
if(DateTime.TryParseExact(readInString, "yyyy-MM-dd", null, DateTimeStyles.AssumeLocal, out dt))
{
if(dt != DateTime.Now.Date)
{
//Code for case where it's no longer that day goes here.
}
}
else
{
//Code for someone messed up the file and it's not a valid date any more goes here.
}
You're doing this for computer-reading, not human-reading, so use the standard format rather than the conventional format (standard as in ISO, but also every country except North Korea has it as the national standard): yyyy-MM-dd (Edit: I see you're in Canada, CSA Z234.5:1989 is the relevant national standard on date-times for technical purposes; it says to use yyyy-MM-dd).
You should do it the other way around, read the string, parse the date, and do the comparison.
you might want to have a look at the FileInfo-Class ... you can compare the LastWriteTime Member to DateTime.Today
DateTime d1 = DateTime.Now;
DateTime d2 = d1.AddMilliseconds(123456789);
string formattedDate = d1.ToString("yyyy/MM/dd");
TimeSpan ts = d2 - d1;
double dayDiff = ts.TotalDays;
double hourDiff = ts.TotalHours;
double minuteDiff = ts.TotalMinutes;
double secondDiff = ts.TotalSeconds;
double milDiff = ts.TotalMilliseconds;
Console.WriteLine("Formatted Date: {0}\r\nDate Diff:\r\nTotal Days: {1}; Total Hours: {2}; Total Minutes: {3}; Total Seconds: {4}; Total Milliseconds: {5}", formattedDate,dayDiff,hourDiff,minuteDiff,secondDiff,milDiff);
Output:
Formatted Date: 2011/12/15
Date Diff:
Total Days: 1.42889802083333; Total Hours: 34.2935525; Total Minutes: 2057.61315; Total Seconds:
123456.789; Total Milliseconds: 123456789
*Edited my initial post to clarify how the "Total" properties work.
//use a TimeSpan do something like this
strCurDate = string.Format(DateTime.Now.ToString(), "yyyy/mm/dd");
FileInfo fiUpdateFileFile = null;
fiUpdateFileFile = new FileInfo(YourFile Location + Your FileName);
if (((TimeSpan)(DateTime.Now - fiUpdateFileFile.LastWriteTime)).TotalHours < 24)
{
// do your logic here...
}
// you could also get at DateTime.Now.Date() or Day.. depending on what you want to do
Suppose a time stamp (just time or date and time) where the time can roll over to the next day:
00:00:00 <- midnight
01:00:00 <- 1 AM
23:00:00 <- 11 PM
24:00:00 <- midnight, day + 1
25:00:00 <- 1 AM, day + 1
What would be a way to parse it easily into a C# DateTime that would perform the carry-over to the next day? In other words, "01:00:00" would become "0001-01-01 01:00:00" and "25:00:00" would become "0001-01-02 01:00:00".
EDIT:
I should mention that this fails miserably (i.e FormatException):
DateTime.ParseExact("0001-01-01 25:00:00", "yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture);
Since you're trying to represent a period of time from an arbitrary point, rather than as a specific date, perhaps you would be better off using the System.TimeSpan class? This allows you to set values of more than 24 hours in the constructor, and can be used with DateTime objects like this:
System.TimeSpan timestamp = new System.TimeSpan(25, 0, 0);
System.DateTime parsedDateTime = new DateTime(0, 0, 0);
parsedDateTime = parsedDateTime.Add(timestamp);
Console.WriteLine(parsedDateTime.ToString("yyyy-MM-dd HH:mm:ss")); //Output as "0001-01-02 01:00:00"
NOTE: Code is untested.
EDIT: In terms of parsing the strings, I can't think of any basic .NET objects that parse strings with values greater than 23 for the hour (since 25 is an invalid hour of the day), but assuming that the format is consistent, you could create a very simple string parsing routine (or even a regular expression) to read the values individually, and load the constructor manually.
If you have an existing DateTime value you can add to, you can always use a TimeSpan:
string dt = "25:00:00";
int hours = int.Parse(dt.Split(':')[0]);
TimeSpan ts = TimeSpan.FromHours(hours);
TimeSpan.Parse() doesn't work directly in this case because it complains (fair enough!) about the 25 in the hour notation.
If you want to code it out... this should be a starting point:
string dateString = "0001-01-01 25:00:00";
string[] parts = dateString.Split(' '); //now have '0001-01-01' and '25:00:00'
string datePart = parts[0]; // '0001-01-01'
string[] timeParts = parts[1].Split(':'); //now have '25', '00', and '00
DateTime initialDate = DateTime.ParseExact(datePart, "yyyy-MM-dd", CultureInfo.InvariantCulture);//use the date as a starting point
//use the add methods to get your desired datetime
int hours = int.Parse(timeParts[0]);
int minutes = int.Parse(timeParts[1]);
int seconds = int.Parse(timeParts[2]);
DateTime resultDate = initialDate.AddHours(hours)
.AddMinutes(minutes)
.AddSeconds(seconds);
Of course, it makes assumptions that the input is formatted properly and is parsable, etc..
In addition, you could definitely use timespan instead of the individual add methods for hour, minute, second as some other answers are..
In case nobody points out an out-of-the-box answer, here is a neat ActionScript class I wrote to parse time inputs (human input)...
https://github.com/appcove/AppStruct/blob/master/Flex/AppStruct/src/AppStruct/TimeInput.as
It would be very simple to port this to C#, and you could tweak the 24 hour logic to result in #days, #hours, #minutes.
Good luck!
You are specifying an invalid date. So not only can you not parse it, you cannot store it!
How about a nice TimeSpan object instead? (It also has a Parse() method.)
Alternatively, use a sscanf()-type function like the one at http://www.blackbeltcoder.com/Articles/strings/a-sscanf-replacement-for-net to extract each number separate. (Best if you have no control over the string format being read.)