功能:
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的二进制 01100110 >>右移一位 = 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的二进制 01100110 >>右移一位 = 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 + "次");} }