功能:
1.签到
2.判断某天是否签到
3.统计某月的签到情况
4.统计某月连续签到了多少天
5.统计某月一共签到了多少次
代码
1.依赖
<dependencies> <dependency> <groupId>redis.clients</groupId> <artifactId>jedis</artifactId> <version>4.0.1</version> </dependency> <dependency> <groupId>cn.hutool</groupId> <artifactId>hutool-all</artifactId> <version>5.8.18</version> </dependency> </dependencies>
2.用户签到
import cn.hutool.core.date.DateField; import cn.hutool.core.date.DateTime; import redis.clients.jedis.Jedis; import java.text.SimpleDateFormat; import java.util.Date; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; public class UserSign { Jedis jedis; public UserSign(Jedis jedis) { this.jedis = jedis; } public String buildKey(int userId, Date date) { return Constant.SING_KEY + userId + ":" + simpleFormatDate(date); } /** * 用户签到 * * @param userId 用户id * @return 签到情况 */ public boolean sign(int userId, Date date) { DateTime now = (DateTime) date; String key = buildKey(userId, now); //这里需要减一是因为偏移量是从0开始的 int offset = now.dayOfMonth() - 1; return jedis.setbit(key, offset, true); } /** * 检测用户是否签到 * * @param userId * @param date * @return */ public boolean isSign(int userId, Date date) { DateTime dateTime = (DateTime) date; return jedis.getbit(buildKey(userId, date), dateTime.getDay() - 1); } /** * 统计签到情况 * * @param userId 用户id * @param date 日期对象 * @return */ public Map<String, Boolean> getSignInfo(int userId, Date date) { Map<String, Boolean> map = new LinkedHashMap<String, Boolean>(); //当月最后一天 DateTime dateTime = (DateTime) date; String type = String.format("u%d", dateTime.getLastDayOfMonth()); //查询当月所签到的二进制值 List<Long> longs = jedis.bitfield(buildKey(userId, date), "get", type, "0"); //判断当月是否有签到情况 if (longs == null || longs.size() == 0) return null; Long aLong = longs.get(0); for (int i = dateTime.getLastDayOfMonth(); i > 0; i--) { DateTime now = DateTime.now(); now.setField(DateField.DAY_OF_MONTH, i); /* 如果二进制右移一位再左移一位等于原来的值,证明低位有0,断签 例如 6的二进制 0110 0110 >>右移一位 = 0011 <<左移回来 0110 还是不变,证明低位有0 */ if (aLong >> 1 << 1 == aLong) { map.put(simpleFormatDate(now, "yyyy-MM-dd"), false); } else { map.put(simpleFormatDate(now, "yyyy-MM-dd"), true); } //右移继续判断下一天 aLong >>= 1; } return map; } /** * 统计连续签到 * * @param userId 用户id * @param date 日期对象 * @return */ public int getContinuousSignNCount(int userId, Date date) { int count = 0; int nowDay = ((DateTime) date).dayOfMonth(); //当月最后一天 String type = String.format("u%d", nowDay); //查询当月所签到的二进制值 List<Long> l = jedis.bitfield(buildKey(userId, date), "get", type, "0"); //当月未签到 if (l == null || l.size() == 0) return 0; //统计 Long aLong = l.get(0); for (int i = 0; i < nowDay; i++) { /* 如果二进制右移一位再左移一位等于原来的值,证明低位有0,断签 例如 6的二进制 0110 0110 >>右移一位 = 0011 <<左移回来 0110 还是不变,证明低位有0 */ if (aLong >> 1 << 1 == aLong) { //这里需要考虑当天没有签到的情况 if (i > 0) break; } else { count += 1; } //右移继续判断下一天 aLong >>= 1; } return count; } /** * 用户某月内一共签到了多少次 * * @param userId 用户id * @param date 日期对象 * @return */ public long signCount(int userId, Date date) { return jedis.bitcount(buildKey(userId, date)); } /** * 固定日期格式 * * @param date * @return */ public static String simpleFormatDate(Date date) { return new SimpleDateFormat("yyyyMM").format(date); } /** * 用户自定义日期格式 *<>java的开闭原则</> * @param date * @param format * @return */ public static String simpleFormatDate(Date date, String format) { SimpleDateFormat simpleDateFormat = new SimpleDateFormat(format); return simpleDateFormat.format(date); } }
3.测试
import cn.hutool.core.date.DateTime; import redis.clients.jedis.Jedis; import java.util.Map; import java.util.Set; public class Test { public static void main(String[] args) throws InterruptedException { Jedis jedis = new Jedis("192.168.57.128", 6379); UserSign userSign = new UserSign(jedis); System.out.println("-----------------签到-----------------"); DateTime now = DateTime.now(); for (int i = 1; i <= 4; i++) { now.setDate(i); System.out.println(now); userSign.sign(100, now); } System.out.println("-----------------查看某一天是否签到-----------------"); DateTime now1 = DateTime.now(); boolean sign = userSign.isSign(100, now1); System.out.println(sign ? UserSign.simpleFormatDate(now1, "yyyy-MM-dd") + ":已签到" : "未签到"); System.out.println("-----------------查看连续签到了几天-----------------"); DateTime now2 = DateTime.now(); int continuousSignNCount = userSign.getContinuousSignNCount(100, now2); System.out.println(UserSign.simpleFormatDate(now2) + "月连续签到了" + continuousSignNCount + "天"); System.out.println("-----------------总体签到情况-----------------"); Map<String, Boolean> signInfo = userSign.getSignInfo(100, DateTime.now()); Set<Map.Entry<String, Boolean>> entries = signInfo.entrySet(); for (Map.Entry<String, Boolean> entry : entries) { System.out.println(entry.getKey() + ":" + (entry.getValue() ? "√" : "X")); } System.out.println("-----------------统计一个月签到了多少天-----------------"); DateTime now3 = DateTime.now(); long l = userSign.signCount(100, now3); System.out.println(UserSign.simpleFormatDate(now3) + "月签到了" + l + "次"); } }