我有一个对象列表,其中包含一个名为date的字符串属性。对象从SQL数据库填充。 date属性包含对象的月份和日期(NO YEAR),格式为MM-DD。我希望能够以某种方式组织这些,以便具有最接近当前日期的下一个日期的对象位于列表的顶部。
我没有在MySQL中使用DateTime对象或Date数据类型的原因是因为我试图阻止每次在一年内过去日期时更新年份。我只是希望能够看到日期即将到来还是已经过去了(显然,如果日期已经过去,它将会出现在列表的底部)。
我知道这种思维方式可能并不理想,并且对此问题的其他建议持开放态度。
编辑:
以下是我正在使用的具体结构的更多信息:
示例数据库信息:
DomainName RenewDate ClientName
mydomain.com 02-01 John Doe
thisdomain.com 08-30 Tim Jones
thatdomain.com 10-10 Jane Smith
对象:
internal class Domain
{
private string name;
private string renewDate;
private string client;
/* Getters, Setters, Constructors, & Other Methods */
}
创建对象后,它们将存储在列表中,我希望根据最接近当前日期的下一个对它们进行排序。例如,如果今天对它进行了排序,则对象的顺序为:
最后的要点是用这些信息填充表格,以便我知道哪些域名续订日期即将到来,这样我就可以手动向客户发送发票。我不认为有必要添加年份,因为每次确切的日期过去我都必须更新它。
同样,我知道这可能不是最有效的解决方法,并且对所有更好的实现建议持开放态度,这只是我目前的过程。
我想出了一些代码,你可以修改你的问题。然而,这可以更加通用(并且更准备更安全)。
class FancyDate
{
public int Month { get; set; }
public int Day { get; set; }
public FancyDate(string fancyDate)
{
var split = fancyDate.Split('-');
Month = Int32.Parse(split[0]);
Day = Int32.Parse(split[1]);
}
public override string ToString()
{
return $"{Month:D2}-{Day:D2}";
}
}
class ClientRenewal
{
public string ClientName { get; set; }
public FancyDate RenewalDate { get; set; }
public string DomainName { get; set; }
public class ClientRenewalComparer : IComparer<ClientRenewal>
{
public int Compare(ClientRenewal x, ClientRenewal y)
{
if (x != null && y != null)
return String.Compare(x.RenewalDate.ToString(), y.RenewalDate.ToString(), StringComparison.Ordinal);
throw new ArgumentNullException();
}
}
public ClientRenewal(string clientName, string renewalDate, string domainName)
{
this.ClientName = clientName;
this.RenewalDate = new FancyDate(renewalDate);
this.DomainName = domainName;
}
public override string ToString()
{
return $"{DomainName} - {RenewalDate} - {ClientName}";
}
}
class ClientRenewalList
{
private List<ClientRenewal> theClientList;
public ClientRenewalList(List<ClientRenewal> list)
{
list.Sort(new ClientRenewal.ClientRenewalComparer());
theClientList = new List<ClientRenewal>();
foreach (var item in list)
{
theClientList.Add(item);
}
}
private List<ClientRenewal> RotateListForCurrentDate()
{
// Bit of indirection to aid testing
return RotateListForDate(DateTime.Now);
}
public List<ClientRenewal> RotateListForDate(DateTime dateTime)
{
var month = dateTime.Month;
var day = dateTime.Day;
int i = 0;
while (i < theClientList.Count)
{
if (theClientList[i].RenewalDate.Month < month)
{
i++;
continue;
}
if (theClientList[i].RenewalDate.Month == month)
{
while (theClientList[i].RenewalDate.Day < day)
{
i++;
}
}
if (theClientList[i].RenewalDate.Month > month) break;
if (theClientList[i].RenewalDate.Month >= month && theClientList[i].RenewalDate.Day >= day) break;
}
return theClientList.Skip(i).Concat(theClientList.Take(i)).ToList();
}
public List<ClientRenewal> GetListForDisplay()
{
return RotateListForCurrentDate();
}
}
static void Main(string[] args)
{
//mydomain.com 02 - 01 John Doe
//thisdomain.com 08 - 30 Tim Jones
//thatdomain.com 10 - 10 Jane Smith
var listOfClientRenewal = new List<ClientRenewal>()
{
new ClientRenewal("John Doe", "02-01", "mydomain.com"),
new ClientRenewal("Tim Jones", "08-30", "thisdomain.com"),
new ClientRenewal("Jane Smith", "10-10", "thatdomain.com")
};
var list = new ClientRenewalList(listOfClientRenewal).GetListForDisplay();
foreach (var item in list)
{
Console.WriteLine(item);
}
}
这是输出:
如果你从数据库中读取它们作为字符串,那么你可以试试这个:
List<string> dates = GetDates(); //returns dates in form MM-DD from db
dates = dates.OrderBy(x=int.Parse(x.Split('-')[0])
.ThenBy(x=>int.Parse(x.Split('-')[1])
.ToList();
List<string> oldDates = new List<string>();
List<string> futureDates = new List<string>();
foreach(var date in dates)
{
string[] splitDate = date.Split('-');
int month = int.Parse(splitDate[0]);
int day = int.Parse(splitDate[1]);
if(month < DateTime.Today.Month)
oldDates.Add(date);
else if(month == DateTime.Today.Month)
{
if(day < DateTime.Today.Day)
oldDates.Add(date);
else
futureDates.Add(date)(
}
else
futureDates.Add(date);
dates = futureDates.AddRange(oldDates);
}
我在移动设备上所以如果可以请格式化:)
你可以将这三个属性添加到你的类中,然后按顺序排序吗?
internal class Domain
{
private string name;
private string renewDate;
private string client;
/* Getters, Setters, Constructors, & Other Methods */
public int LastRenewalDateMonth => int.Parse(renewDate.Split('-')[0]);
public int LastRenewalDateDay => int.Parse(renewDate.Split('-')[1]);
public DateTime LastRenewalDate => new DateTime(1901, LastRenewalDateMonth, LastRenewalDateDay);
}
就像你说的那样,你不关心这一年。
希望这可以帮助。
如果我正确理解您的要求,则以下内容应足够:
List<string> dates = new List<string>() { "02-01", "08-30", "10-10" };
CultureInfo ci = CultureInfo.InvariantCulture;
var sorted = dates.Select(s => DateTime.ParseExact(s, "MM-dd", ci))
.OrderBy(d => d);
var customSorted = sorted.SkipWhile(d => d <= DateTime.Today)
.Concat(sorted.TakeWhile(d => d <= DateTime.Today));
// In case you want them back as strings, otherwise, ignore the
// following line and add a `.ToList()` to the above line.
var customSortedStrings = customSorted.Select(d => d.ToString("MM-dd")).ToList();
foreach (string s in customSortedStrings)
Console.WriteLine(s);
输出:
10-10
02-01
08-30