C# MVC 3 中临近到期时更改日期文本颜色
支付阿杰
结论
不要将 DateTime.Now.AddDays(...) 与 true 比较。AddDays 返回 DateTime,不是布尔值,这样的条件无法成立。
可以直接判断当前日期距离 BillingEndDate 还有多少天,再根据到期日是否进入提醒区间设置 CSS 类。日期只需输出一次。
Razor 中的简单实现
假设所有计费周期都在到期前 7 天显示为红色:
@{
DateTime today = DateTime.Today;
DateTime expiryDate = Model.BillingEndDate.Date;
bool isNearExpiry =
expiryDate >= today &&
expiryDate <= today.AddDays(7);
string expiryClass = isNearExpiry ? "billing-expiring" : "billing-normal";
}
<div>
Billing Expiry Date:
<span class="@expiryClass">
@Model.BillingEndDate.ToLongDateString()
</span>
</div>
对应的 CSS:
.billing-expiring {
color: red;
}
.billing-normal {
color: white;
}
这里判断的是日期范围,而不是两个 DateTime 是否完全相等。到期日只要落在今天至未来 7 天内,文本就会变红。
不同计费周期使用不同提醒时间
如果 monthly、6 month 和 yearly 对应不同的提前提醒天数,可以先根据 BillingCycleID 设置阈值:
@{
int warningDays;
switch (Model.BillingCycleID)
{
case 1: // Monthly
warningDays = 7;
break;
case 2: // 6 months
warningDays = 14;
break;
case 3: // Yearly
warningDays = 30;
break;
default:
warningDays = 7;
break;
}
DateTime today = DateTime.Today;
DateTime expiryDate = Model.BillingEndDate.Date;
bool isNearExpiry =
expiryDate >= today &&
expiryDate <= today.AddDays(warningDays);
string expiryClass = isNearExpiry ? "billing-expiring" : "billing-normal";
}
<span class="@expiryClass">
@Model.BillingEndDate.ToLongDateString()
</span>
warningDays 应按照实际业务规则设置。计费周期长度与提前提醒天数是两个概念,不能因为周期是 6 个月,就直接换算成 176 天来判断是否临近到期。
区分临近到期和已经过期
如果已经过期的账户也需要显示为红色,可以将日期分为三种状态:
@{
DateTime today = DateTime.Today;
DateTime expiryDate = Model.BillingEndDate.Date;
int warningDays = 7;
string expiryClass;
if (expiryDate < today)
{
expiryClass = "billing-expired";
}
else if (expiryDate <= today.AddDays(warningDays))
{
expiryClass = "billing-expiring";
}
else
{
expiryClass = "billing-normal";
}
}
<span class="@expiryClass">
@Model.BillingEndDate.ToLongDateString()
</span>
.billing-expired {
color: red;
font-weight: bold;
}
.billing-expiring {
color: red;
}
.billing-normal {
color: white;
}
在 ViewModel 中完成判断
日期状态属于业务展示逻辑。页面变得复杂后,可以在控制器或 ViewModel 中完成计算,避免在 Razor 视图中堆放大量判断代码。
public class BillingViewModel
{
public int BillingCycleID { get; set; }
public DateTime BillingStartDate { get; set; }
public DateTime BillingEndDate { get; set; }
public bool IsBillingNearExpiry { get; set; }
public bool IsBillingExpired { get; set; }
}
在控制器或业务层赋值:
DateTime today = DateTime.Today;
DateTime expiryDate = model.BillingEndDate.Date;
int warningDays = 7;
model.IsBillingExpired = expiryDate < today;
model.IsBillingNearExpiry =
!model.IsBillingExpired &&
expiryDate <= today.AddDays(warningDays);
视图只处理显示:
@{
string expiryClass = Model.IsBillingExpired
? "billing-expired"
: Model.IsBillingNearExpiry
? "billing-expiring"
: "billing-normal";
}
<span class="@expiryClass">
@Model.BillingEndDate.ToLongDateString()
</span>
根据开始日期计算结束日期
如果数据库中没有确定的 BillingEndDate,应使用 AddMonths 或 AddYears 计算结束日期,不要用固定天数模拟月份:
switch (model.BillingCycleID)
{
case 1:
model.BillingEndDate = model.BillingStartDate.AddMonths(1);
break;
case 2:
model.BillingEndDate = model.BillingStartDate.AddMonths(6);
break;
case 3:
model.BillingEndDate = model.BillingStartDate.AddYears(1);
break;
default:
throw new ArgumentOutOfRangeException("BillingCycleID");
}
一个月可能有 28、29、30 或 31 天,因此 AddMonths(1) 比 AddDays(30) 更符合月度计费规则。
注意事项
- 使用
.Date可以忽略时、分、秒,避免因时间不同而无法识别到期日当天。 - 不要使用
DateTime.Now.AddDays(7) == BillingEndDate。即使两边类型一致,毫秒差异也很容易让结果变成false。 - 如果系统涉及多个时区,需要先确定账单日期使用服务器时间、用户本地时间还是 UTC,然后再进行比较。
- 如果只有特定账户需要显示为红色,可以将账户条件加入判断:
bool shouldHighlight =
Model.AccountID == 2 &&
expiryDate >= today &&
expiryDate <= today.AddDays(warningDays);
这样,Account 2 临近到期时会显示为红色,其他账户仍使用默认颜色。
备注:内容仅供参考。
