说明
签到功能根据业务情况的不同大致分为两种,一种是只要进入系统就会默认签到,另外一种是进入系统之后需要用户手动点击签到按钮进行签到。两种情况最大的区别就是,自动签到连续签到天数肯定至少为1天。而手动签到的情况则需要考虑断签的情况。
自动签到下统计连续签到天数
public static void main(String[] args) {
try {
/**
* 造一些测试数据,这里就不去数据库里查了,一般正常是数据库有个表记录签到记录
*/
List<String> signInDateStrs = new ArrayList<>();
signInDateStrs.add("2019-12-31");
signInDateStrs.add("2020-01-01");
signInDateStrs.add("2020-01-02");
List<Date> signInDates = new ArrayList<>();
for (String dateStr : signInDateStrs) {
Calendar calendarTo = Calendar.getInstance();
calendarTo.setTime(new SimpleDateFormat("yyyy-MM-dd").parse(dateStr));
Calendar c = Calendar.getInstance();
c.setTimeInMillis(0);
c.set(calendarTo.get(Calendar.YEAR), calendarTo.get(Calendar.MONTH),
calendarTo.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
signInDates.add(c.getTime());
}
int count = persistentDay(signInDates);
System.out.println("连续签到了" + count + "天");
} catch (ParseException e) {
e.printStackTrace();
}
}
/**
* 自动签到的情况,只要一进入系统就会签到,所以连续签到肯定至少为1天
* @param signInDates
* @return
*/
private static int persistentDay(List<Date> signInDates){
//定义一个变量表示连续签到天数,从1开始
int continuousDays = 1;
//1. 注意先对时间进行从小到大排序(可以在数据库里查的时候就根据时间排序,也可以查询出来之后再排序)
/**
* 2. 从最大的时间开始往前比较,因为我们是要拿连续签到的时间,这样才有意义,减少无谓的比较
*/
Calendar later = Calendar.getInstance();
Calendar before = Calendar.getInstance();
for (int i = signInDates.size() - 1; i > 0; i--){
later.setTime(signInDates.get(i));
before.setTime(signInDates.get(i - 1));
//前一天 + 1天 = 后一天,则视为连续签到
before.add(Calendar.DAY_OF_MONTH,1);
if (later.get(Calendar.YEAR) == before.get(Calendar.YEAR)
&& later.get(Calendar.MONTH) == before.get(Calendar.MONTH)
&& later.get(Calendar.DAY_OF_YEAR) == before.get(Calendar.DAY_OF_YEAR)){
continuousDays++;
}else {
//只要遇到不连续的就不用再往前比较了
break;
}
}
return continuousDays;
}
手动签到下统计连续签到天数
public static void main(String[] args) {
/**
* 造一些测试数据,为了简单演示就不去数据库查寻签到记录了
* 注意时间要从小到大排序,如果从数据库里查询的时候,可以根据这个时间进行order by
* 也可以查询出来再程序排序
*/
List<String> signInDateStrs = new ArrayList<>();
signInDateStrs.add("2019-12-31");
signInDateStrs.add("2020-03-02");
signInDateStrs.add("2020-03-03");
List<Date> signInDates = new ArrayList<>();
try {
for (String dateStr : signInDateStrs) {
Calendar calendarTo = Calendar.getInstance();
calendarTo.setTime(new SimpleDateFormat("yyyy-MM-dd").parse(dateStr));
Calendar c = Calendar.getInstance();
c.setTimeInMillis(0);
c.set(calendarTo.get(Calendar.YEAR), calendarTo.get(Calendar.MONTH),
calendarTo.get(Calendar.DAY_OF_MONTH), 0, 0, 0);
signInDates.add(c.getTime());
}
} catch (ParseException e) {
e.printStackTrace();
}
int count = persistentDay(signInDates);
System.out.println("已连续签到 " + count + "天");
}
/**
* 需要手动点击签到的情况
* @param signInDates
* @return
*/
private static int persistentDay(List<Date> signInDates) {
//定义一个变量表示连续签到天数,从1开始
int continuousDays = 1;
/**
* 如果手动签到的话需要考虑
* 把排序之后的签到记录时间中最大的那个时间拿出来与 昨天 进行比较,如果相等证明还是连续签到的,如果不等则连续签到变成0
*/
Calendar yesterday = Calendar.getInstance();
yesterday.setTime(new Date());
yesterday.add(Calendar.DAY_OF_MONTH, -1);
Calendar lastDay = Calendar.getInstance();
lastDay.setTime(signInDates.get(signInDates.size() - 1));
if (yesterday.get(Calendar.YEAR) != lastDay.get(Calendar.YEAR)
|| yesterday.get(Calendar.MONTH) != lastDay.get(Calendar.MONTH)
|| yesterday.get(Calendar.DAY_OF_YEAR) != lastDay.get(Calendar.DAY_OF_YEAR)) {
//昨天没有签到
continuousDays = 0;
return continuousDays;
}
/**
* 2. 从最大的时间开始往前比较,因为我们是要拿连续签到的时间,这样才有意义,减少无谓的比较
*/
Calendar later = Calendar.getInstance();
Calendar before = Calendar.getInstance();
for (int i = signInDates.size() - 1; i > 0; i--) {
later.setTime(signInDates.get(i));
before.setTime(signInDates.get(i - 1));
//前一天 + 1天 = 后一天,则视为连续签到
before.add(Calendar.DAY_OF_MONTH, 1);
if (later.get(Calendar.YEAR) == before.get(Calendar.YEAR)
&& later.get(Calendar.MONTH) == before.get(Calendar.MONTH)
&& later.get(Calendar.DAY_OF_YEAR) == before.get(Calendar.DAY_OF_YEAR)) {
continuousDays++;
} else {
//只要遇到不连续的就不用再往前比较了
break;
}
}
return continuousDays;
}