I have a string variable that holds the value of "02/04/2018 to 08/04/2018".
string dateRange = "02/04/2018 to 08/04/2018";
I have a function in c# that gets all the date within the range of 02/04/2018 to 08/04/2018 as per below.
public string getDateRange(string dateRange) {
var selectedDates = new List<DateTime?>();
for (var date = Convert.ToDateTime("02/04/2018");
date <= Convert.ToDateTime("08/04/2018");
date = date.AddDays(1)) {
selectedDates.Add(date);
}
foreach (var date in selectedDates) {
Console.WriteLine(date);
}
return selectedDates;
}
What I want to achieve in this method is to remove the word to in the date range and pass the starting date and ending date separately. Can someone please help ?
You can use String.Split() to separate the dates:
public string[] separateDates(string dateRange)
{
string[] dateSplit = dateRange.Split(new string[] { "to" }, StringSplitOptions.RemoveEmptyEntries);
return new string[]{dateSplit[0].Trim(), dateSplit[1].Trim()};
}
The method returns a string array that holds the first ("02/04/2018") and the second date ("08/04/2018"):
static void Main()
{
string dateRange = "02/04/2018 to 08/04/2018";
string[] myDates = separateDates(dateRange);
string firstDate = myDates[0];//"02/04/2018"
string secondDate = myDates[1];//"08/04/2018"
}
EDIT:
I have implemented my method that separates the dates into your method:
public List<DateTime?> getDateRange(string dateRange)
{
var selectedDates = new List<DateTime?>();
string[] dateSplit = dateRange.Split(new string[] { "to" }, StringSplitOptions.RemoveEmptyEntries);
for (var date = Convert.ToDateTime(dateSplit[0].Trim());
date <= Convert.ToDateTime(dateSplit[1].Trim());
date = date.AddDays(1))
{
selectedDates.Add(date);
}
foreach (var date in selectedDates)
{
Console.WriteLine(date.Value.ToString("dd/MM/yyyy", CultureInfo.InvariantCulture));
}
return selectedDates;
}
The method now returns List<DateTime?> instead of string because the type of selectedDates is List<DateTime?>. I also made a modification to the console output, now the dates are printing to the console in the following format dd/MM/yyyy (e.g. 02/04/2018).
LastIndexOf: This method searches strings from the right. It finds the location of the last occurrence of a letter or substring. It is the reversed version of IndexOf.
public static void Main(string[] args)
{
string str = "02/04/2018 to 08/04/2018";
int pos = str.LastIndexOf("to");
string result = str.Substring(0, pos) + " " + str.Substring(pos + 2);
Console.WriteLine(result);
}
Fiddle
Its printing the date as : 02.04.2018 00:00:00. I have specified the string to dd/MM/yyyy. It just removes the 00:00:00 but keeps the dot in between.
Here is the little amendment to fix that:
Console.WriteLine(date.Value.ToString("dd/MM/yyyy"));
Related
I have written a logic in c# that determines the nextCallDate based on the given cobDate. cobDate is current date -1.
So if there are more than one future date in the given string then it should return the nearest future date to the cobdate and ignore the rest
For eg if the cobdate is 2020/02/12 and the string is
;2;4;2;5;20180328;3;103.3750;5;20190328;3;102.250;5; 20200328;3;101.1250;5;20210328;3;100.00;
Then NextCallDate would be 2020/03/28.
I need to return blank for dates in the past.
So say in the example if the given string has all the dates in the past then it should return blank.
Given string ;2;1;2;5;20120918;3;100.000000;
Here is what I have written
private DateTime? GetNextCallDate(string nextCallDate)
{
DateTime cobDate = DateTime.Now.Date.AddDays(-1);
var parts = nextCallDate.Split(';');
foreach (var part in parts)
{
DateTime parsedNextCallDate = DateTime.Parse(part);
if (parsedNextCallDate.Date > cobDate.Date)
{
return parsedNextCallDate;
}
}
return null;
}
You should probably be using DateTime.TryParse instead of Parse, since some of the values are not dates. Also, it looks like you're returning the first date that's greater than cobDate, not the nearest one.
To resolve this, we first set parsedNextCallDate to null, and this will be our default return value. Then we can check each part if it's a DateTime using the return value from TryParse, and then compare the value to both cobDate and parsedNextCallDate. If the date is greater than cobDate and less than parasedNextCallDate (or if parasedNextCallDate isn't set yet), then we update parasedNextCallDate to the new value. At the end, we just return parasedNextCallDate:
public static DateTime? GetNextCallDate(string input)
{
DateTime? nextCallDate = null;
if (string.IsNullOrWhiteSpace(input)) return nextCallDate;
var yesterday = DateTime.Today.AddDays(-1);
var inputItems = input.Split(';');
foreach (var inputItem in inputItems)
{
DateTime itemDate;
// If inputItem is a DateTime and it's greater than yesterday
if (DateTime.TryParseExact(inputItem.Trim(), "yyyyMMdd", null,
DateTimeStyles.None, out itemDate) &&
itemDate.Date > yesterday)
{
// and if nextCallDate doesn't have a value or the parsed value
// is less than nextCallDate, assign nextCallDate to this value
if (!nextCallDate.HasValue || itemDate < nextCallDate)
{
nextCallDate = itemDate;
}
}
}
return nextCallDate;
}
Here's one way solve your problem. Breaking things down into steps often makes things easier to reason with and easier to test. I'm often working on server side apps so I like the new span/memory classes. So first thing is to split our input string into chunks:
static IEnumerable<ReadOnlyMemory<char>> ReduceToPossibleDates(string source)
{
const int ExpectedDateLen = 9; // includes separator
int last = 0;
var mem = source.AsMemory();
for (int i = 0; i < source.Length; ++i)
{
if (';' == mem.Span[i])
{
int length = i - last;
if (length == ExpectedDateLen)
{
yield return mem.Slice(last+1,length-1);
}
last = i;
}
}
}
This gives us a stream of ReadOnlyMemory that all contains what we think should be dates. Next we can do another method to consume those chunks and turn them into dates.
static IEnumerable<DateTime> ToDateTime(IEnumerable<ReadOnlyMemory<char>> rawDates)
{
foreach (var rawDate in rawDates)
{
if (DateTime.TryParseExact(rawDate.Span,"yyyyMMdd".AsSpan(),
CultureInfo.InvariantCulture,
DateTimeStyles.None, out var date))
yield return date;
}
}
Once we have that we can treat the stream of dates however we want. In this case we check to find the first that's after our COB.
static void Main(string[] _)
{
const string GoodData = ";2;4;2;5;20180328;3;103.3750;5;20190328;3;102.250;"+
"5;20200328;3;101.1250;5;20210328;3;100.00;";
const string NoDateData = ";2;1;2;5;20120918;3;100.000000;";
var cobDate = new DateTime(2020, 2,12); // some actual close of business date...
var nextCallDate = ToDateTime(ReduceToPossibleDates(GoodData))
.FirstOrDefault(x => x >= cobDate);
var noDateExpected = ToDateTime(ReduceToPossibleDates(NoDateData))
.FirstOrDefault(x => x >= cobDate);
if (nextCallDate != default(DateTime))
Console.WriteLine(nextCallDate);
else
Console.WriteLine("no call date.");
if (noDateExpected != default(DateTime))
Console.WriteLine(nextCallDate);
else
Console.WriteLine("no call date.");
}
It would be a little cleaner with extension methods but you get the idea.
I have two arrays, UserActivity and UserDateTime. User Activity array holds the activities of what the user is doing and the UserDateTime holds the DateTime of the said activity. I cannot find a solution where I can output the DateTime where it's greater than such Date/Time whilst printing out the user activity.
For example:
[UserDateTime] [UserActivity]
02/02/2018 02:20 User logs on
05/02/2018 15:20 User visits page
20/02/2018 16:10 User goes here
21/02/2018 12:00 User logs off
21/02/2018 13:00 User logs on
21/02/2018 15:00 User visits here
The Date and time has its own array (UserDateTime) while the users' activity is in the array UserActivity'.
etc.
My problem is that I can't programmatically output where the DateTime is greater than 20/02/2019 and the User Activity is linked to the date/time.
My code is followed:
string[] UserActivity = File.ReadAllLines(#"useractivityfile");
string[] UserDateTime = File.ReadAllLines(#"userdatetimesfile");
DateTime greaterthanthis = new DateTime(2018, 2, 20);
for (int i = 0; i < UserActivity.Length; i++)
{
if (DateTime.ParseExact(UserDT[i], "dd/MM/yyyy", CultureInfo.InvariantCulture) > greaterthanthis)
{
Console.WriteLine(UserDT[i].Where(x >= greaterthanthis????); //very stuck on this part
//Also want to link the useractivity so Console.WriteLine(UserDT[i] + UserDT[i])
}
}
I've been overthinking and overcomplicating this code all week (stressed). Thank you for your help.
Try this pls. The format of the string representation must match a specified format exactly or an exception is thrown.
string[] UserActivity = File.ReadAllLines(#"path");
string[] UserDateTime = File.ReadAllLines(#"path");
DateTime greaterthanthis = new DateTime(2018, 2, 20);
for (int i = 0; i < UserActivity.Length; i++)
{
if (DateTime.ParseExact(UserDateTime[i], "dd/MM/yyyy HH:mm", CultureInfo.InvariantCulture) > greaterthanthis)
{
Console.WriteLine(UserDateTime[i].ToString() + " : " + UserActivity[i]);
}
}
There is plenty of typo in your code:
for (int i = 0; x < UserActivity.Length; i++)
=> for (int i = 0; i < UserActivity.Length; i++)
if (DateTime.ParseExact(UserDT[i], "dd/MM/yyyy", CultureInfo.InvariantCulture > greaterthanthis ) )
=> if (DateTime.ParseExact(UserDT[i], "dd/MM/yyyy", CultureInfo.InvariantCulture ) > greaterthanthis)
The ParseExact format match your 1rst version but doesn't match your file format
The easier step will be to get away from those files and make a reasonable object out of it:
public class Logs
{
public DateTime Date { get; set; }
public string Name { get; set; }
public string Activity { get; set; }
}
Note that you example bothe file don't have the same number of lines...
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
public class Logs
{
public DateTime Date { get; set; }
public string Name { get; set; }
public string Activity { get; set; }
}
public static void Main(string[] args)
{
var UserDateTime_TEXT = #"02/02/2018 02:20
05/02/2018 15:20
21/02/2018 12:00
21/02/2018 13:00
21/02/2018 15:00 ";
var UserActivity_TEXT = #"User logs on
User visits page
User goes here
User logs off
User logs on
User visits here";
//Equivalent to ReadAllLines
string[] UserDateTime = UserDateTime_TEXT.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
string[] UserActivity = UserActivity_TEXT.Split(new[] { Environment.NewLine }, StringSplitOptions.RemoveEmptyEntries);
// ps in your exemple there is more activity than date time...
// UserDateTime.Length != UserActivity.Length !!!!!!!!!!!
var data = new List<Logs>();
//in your code you had `x < UserActivity.Length`, what is x?
for (int i = 0; i < UserDateTime.Length; i++)
{
var splitValues = UserActivity[i].Split(' ');
var temp =
new Logs
{
Date = DateTime.ParseExact(UserDateTime[i].Trim(), "dd/MM/yyyy HH:mm", CultureInfo.InvariantCulture),
Name = splitValues[0], // No space in username.
Activity = string.Join(" ", splitValues.Skip(1))
};
data.Add(temp);
}
//filter
var greaterThanThis = new DateTime(2018, 2, 20);
var result = data.Where(x=> x.Date > greaterThanThis);
foreach(var entry in data){
Console.WriteLine($"{entry.Name} did {entry.Activity} at {entry.Date}");
}
}
Live Demo
Frankly speaking, your code looks like a complete mess. Brackets were wrong, variable names were wrong, LINQ query was wrong as well.
Use this as a start:
string[] UserActivity = File.ReadAllLines(#"useractivityfile");
string[] UserDateTime = File.ReadAllLines(#"userdatetimesfile");
DateTime greaterthanthis = new DateTime(2019, 1, 12);
for (int i = 0; i < UserActivity.Length; i++)
{
if (DateTime.ParseExact(UserDateTime[i], "dd/MM/yyyy", CultureInfo.InvariantCulture) > greaterthanthis)
{
Console.WriteLine(UserDateTime[i]);
//Also want to link the useractivity so Console.WriteLine(UserDT[i] + UserDT[i])
}
}
If you want a LINQ query, try this:
UserDateTime.Where(x => DateTime.ParseExact(x, "dd/MM/yyyy", CultureInfo.InvariantCulture) > greaterthanthis).ToList().ForEach(dt => Console.WriteLine(dt));
But I recommend to stay with the upper code for an easier overview and debugging.
I have an array that stores date input from users but I want to remove or trim the first two characters (basically, I want to remove the month) from every date inputted in the array:
class MainClass
{
{
//Main Program....
}
public static int GetInput (string[] date)
{
int loop;
(for int i=0 ; i < loop ; i++)
dArray[i] = Console.ReadLine();
}
}
class OtherClass
{
//Required data properties, etc...
public string TrimFirstTwoMonthChar(string dateInput)
{
char[] delimiter = {'/', '-', .... }
string[] monthNumberRemoved = dateInput.Split(delimeter);
// How would I code the rest of this function so that it removes the first 2 characters from "MM/dd/yyyy".
//Keep in mind I have also allowed users to input the date in formats like
//"M/dd/yyyy" (such as 3/07/2011 vs 03/07/2011)
//so sometimes I would only need to remove ONE NOT TWO of the month character //
}
}
With string, you can use a simple substring:
public static string TrimFirstTwoMonthChar(string dateInput)
{
var indexOfFirstBar = dateInput.IndexOf('/');
var start = indexOfFirstBar + 1;
return dateInput.Substring(start, dateInput.Length - start);
}
But I suggest you to convert to DateTime and use the date format you want:
public static string TrimFirstTwoMonthChar(string dateInput)
{
var date = Convert.ToDateTime(dateInput);
return date.ToString("dd/yyyy"); // Use the format you want here
}
About Convert.ToDateTime and date formats.
Something like this?
public string TrimFirstTwoMonthChar(string dateInput)
{
char[] delimiter = {'/', '-', .... }
string[] monthNumberRemoved = dateInput.Split(delimeter);
return monthNumberRemoved[1] + "/" + monthNumberRemoved[2];
}
I'm getting UTC time from devices that appear in arabic unicode. How can I convert this format to a DateTime object?
Here is an example of the date format:
٢٠١٤-١٢-٢٨T٢١:٤١:٥٨Z
For the curious, it should translate to:
2014/12/28 21:41:58
Combining How to convert Arabic number to int? and How to create a .Net DateTime from ISO 8601 format:
static void Main(string[] args)
{
string input = "٢٠١٤-١٢-٢٨T٢١:٤١:٥٨Z";
string output = ReplaceArabicNumerals(input);
var dateTime = DateTime.Parse(output, null, DateTimeStyles.AssumeUniversal);
Console.WriteLine(output);
Console.WriteLine(dateTime.ToString("u"));
Console.ReadKey();
}
public static string ReplaceArabicNumerals(string input)
{
string output = "";
foreach (char c in input)
{
if (c >= 1632 && c <= 1641)
{
output += Char.GetNumericValue(c).ToString();
}
else
{
output += c;
}
}
return output;
}
Yields 2014-12-28T21:41:58Z and 2014-12-28 21:41:58Z.
Explanation of the ReplaceArabicNumerals() method: when it detects an Arabic-Indic numeral (between code point 1632 (0) and 1641 (9)), it requests the numerical value of the character. This translates the East-Arabic numerals into West-Arabic ones that .NET can parse.
I have a textBox1 showing text = 01/02/2013, and I have
string year, month, day.
How to set
year=2013,
month=02,
day=01
from textbox1
var text = "01/02/2013";
var parts = text.Split('/');
var day = parts[0];
var month = parts[1];
var year = parts[2];
Just to be different and to add a solution that is not splitting the string, here is one converting the string to a DateTime and pulling the information out of the resulting DateTime Object.
class Program
{
static void Main(string[] args)
{
string myString = "01/02/2013";
DateTime tempDate;
if (!DateTime.TryParse(myString, out tempDate))
Console.WriteLine("Invalid Date");
else
{
var month = tempDate.Month.ToString();
var year = tempDate.Year.ToString();
var day = tempDate.Day.ToString();
Console.WriteLine("The day is {0}, the month is {1}, the year is {2}", day, month, year);
}
Console.ReadLine();
}
}
Use string.Split to get each string
string s = "01/02/2013";
string[] words = s.Split('/');
foreach (string word in words)
{
Console.WriteLine(word);
}
Try this Regex
(?<month>\d{1,2})\/(?<day>\d{1,2})\/(?<year>\d{4})
I/P:
2/7/2014
O/P:
month 2
day 7
year 2014
REGEX DEMO
(Or)
Try by String.Split method
string[] separators = {"-","/",":"};
string value = "01/02/2013";
string[] words = value.Split(separators, StringSplitOptions.RemoveEmptyEntries);
foreach (void word_loopVariable in words)
{
word = word_loopVariable;
Console.WriteLine(word);
}