#c#
#c#
Вопрос:
Я написал логику на c #, которая определяет nextCallDate на основе заданной cobDate. cobDate — это текущая дата -1.
Итак, если в данной строке есть более одной будущей даты, тогда она должна возвращать ближайшую будущую дату в cobdate и игнорировать остальные
Например, если cobdate равен 2020/02/12, а строка ;2;4;2;5;20180328;3;103.3750;5;20190328;3;102.250;5; 20200328;3;101.1250;5;20210328;3;100.00;
Тогда NextCallDate будет 2020/03/28 .
Мне нужно вернуть пробел для дат в прошлом. Скажем, в примере, если данная строка содержит все даты в прошлом, тогда она должна возвращать пустое значение. Заданная строка ;2;1;2;5;20120918;3;100.000000;
Вот что я написал
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;
}
Комментарии:
1. Что возвращает ваша функция?
2. это возвращает дату
3. Что вы подразумеваете под «пустым»? Вы имеете в виду
null
?4. Вероятно, вы должны использовать
DateTime.TryParse
вместоParse
, поскольку некоторые значения не являются датами. Кроме того, похоже, что вы возвращаете первую дату, которая больше, чемcobDate
, а не ближайшую.5. Я имел в виду необходимость возврата null
Ответ №1:
Вероятно, вам следует использовать DateTime.TryParse
вместо Parse
, поскольку некоторые значения не являются датами. Кроме того, похоже, что вы возвращаете первую дату, которая больше, чем cobDate, а не ближайшую.
Чтобы решить эту проблему, мы сначала устанавливаем parsedNextCallDate
значение null
, и это будет возвращаемое значение по умолчанию. Затем мы можем проверить каждую часть, является ли она a DateTime
, используя возвращаемое значение from TryParse
, а затем сравнить значение с обоими cobDate
и parsedNextCallDate
. Если дата больше cobDate
и меньше parasedNextCallDate
(или если parasedNextCallDate
она еще не установлена), то мы обновляем parasedNextCallDate
до нового значения. В конце мы просто возвращаем 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) amp;amp;
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;
}
Ответ №2:
Вот один из способов решения вашей проблемы. Разбиение вещей на этапы часто упрощает рассуждения и упрощает тестирование. Я часто работаю над серверными приложениями, поэтому мне нравятся новые классы span / memory. Итак, первое, что нужно разбить нашу входную строку на куски:
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;
}
}
}
Это дает нам поток ReadOnlyMemory, который содержит все, что, по нашему мнению, должно быть датами. Далее мы можем использовать другой метод для использования этих фрагментов и превращения их в даты.
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;
}
}
Как только мы получим это, мы сможем обрабатывать поток дат так, как захотим. В этом случае мы проверяем, чтобы найти первую после нашего 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.");
}
Это было бы немного чище с методами расширения, но вы поняли идею.