goland使用redis实现签到功能

ops/2024/10/16 2:26:53/
签到封装:直接调用即可,基本满足所有签到操作
package mainimport ("context""fmt""time""github.com/go-redis/redis/v8"
)type UserSign struct {rdb *redis.Client
}func NewUserSign(opt *redis.Options) *UserSign {return &UserSign{rdb: redis.NewClient(opt)}
}func (us *UserSign) Sign(userID int64, date time.Time) error {key := fmt.Sprintf("user:%d:sign:%d-%02d-%02d", userID, date.Year(), date.Month(), date.Day())_, err := us.rdb.SetNX(context.Background(), key, 1, 0).Result()return err
}func (us *UserSign) GetMonthSignCount(userID int64, year int, month time.Month) (int, error) {signCount := 0startOfMonth := time.Date(year, month, 1, 0, 0, 0, 0, time.UTC)nextMonth := startOfMonth.AddDate(0, 1, 0)for currentDate := startOfMonth; currentDate.Before(nextMonth); currentDate = currentDate.AddDate(0, 0, 1) {key := fmt.Sprintf("user:%d:sign:%d-%02d-%02d", userID, currentDate.Year(), currentDate.Month(), currentDate.Day())exists, err := us.rdb.Exists(context.Background(), key).Result()if err != nil {return 0, err}if exists > 0 {signCount++}}return signCount, nil
}// GetUserMonthlySignDetails 获取用户在指定年份内每个月的签到次数及详细情况
func (us *UserSign) GetUserMonthlySignDetails(userID int64, year int) (map[string][]string, map[string]int, error) {details := make(map[string][]string)counts := make(map[string]int)for month := time.January; month <= time.December; month++ {mo := int(month)monthStr := fmt.Sprintf("%d-%02d", year, mo)daysInMonth := time.Date(year, month+1, 0, 0, 0, 0, 0, time.UTC).Day()signDates := []string{}for day := 1; day <= daysInMonth; day++ {date := time.Date(year, month, day, 0, 0, 0, 0, time.UTC)key := fmt.Sprintf("user:%d:sign:%d-%02d-%02d", userID, date.Year(), date.Month(), date.Day())exists, err := us.rdb.Exists(context.Background(), key).Result()if err != nil {return nil, nil, err}if exists > 0 {signDates = append(signDates, date.Format("2006-01-02"))}}details[monthStr] = signDatescounts[monthStr] = len(signDates)}return details, counts, nil
}// GetSignDetailsInRange 获取用户在指定日期范围内的签到详细情况
func (us *UserSign) GetSignDetailsInRange(userID int64, startDate, endDate time.Time) ([]string, error) {var signDates []stringcurrentDate := startDatefor currentDate.Before(endDate) || currentDate.Equal(endDate) {key := fmt.Sprintf("user:%d:sign:%d-%02d-%02d", userID, currentDate.Year(), currentDate.Month(), currentDate.Day())exists, err := us.rdb.Exists(context.Background(), key).Result()if err != nil {return nil, err}if exists > 0 {signDates = append(signDates, currentDate.Format("2006-01-02"))}currentDate = currentDate.AddDate(0, 0, 1)}return signDates, nil
}func (us *UserSign) CompensateSign(userID int64, date time.Time) error {key := fmt.Sprintf("user:%d:sign:%d-%02d-%02d", userID, date.Year(), date.Month(), date.Day())_, err := us.rdb.SetNX(context.Background(), key, 1, 0).Result()return err
}func main() {opt, err := redis.ParseURL("redis://localhost:6379")if err != nil {panic(err)}userSign := NewUserSign(opt)// 示例:用户1在今天的日期签到now := time.Now()err = userSign.Sign(1, now)if err != nil {fmt.Println("签到失败:", err)} else {fmt.Println("签到成功")}// 示例:获取用户1本月签到次数count, err := userSign.GetMonthSignCount(1, now.Year(), now.Month())if err != nil {fmt.Println("获取签到次数失败:", err)} else {fmt.Printf("本月签到次数: %d\n", count)}// 示例:为用户1在指定日期(例如昨天)补签yesterday := now.AddDate(0, 0, -1)err = userSign.CompensateSign(1, yesterday)if err != nil {fmt.Println("补签失败:", err)} else {fmt.Println("补签成功")}yearToCheck := time.Now().Year() // 查询本年度的签到情况,可以根据需要替换为其他年份// 示例:获取用户1本年度每个月的签到详细情况和次数details, counts, err := userSign.GetUserMonthlySignDetails(1, yearToCheck)if err != nil {fmt.Println("获取每月签到详情失败:", err)} else {for month, dates := range details {fmt.Printf("月份: %s, 签到次数: %d, 详细情况: %v\n", month, counts[month], dates)}}startDate := time.Date(2024, 5, 1, 0, 0, 0, 0, time.UTC)endDate := time.Date(2024, 5, 31, 23, 59, 59, 0, time.UTC) // 注意结束时间通常设置为月末的最后一秒signDetails, err := userSign.GetSignDetailsInRange(1, startDate, endDate)if err != nil {fmt.Println("获取签到详情失败:", err)} else {fmt.Printf("指定日期范围内的签到详细情况: %v\n", signDetails)}
}


http://www.ppmy.cn/ops/119105.html

相关文章

Linux云计算 |【第四阶段】PROJECT2-DAY1

综合项目内容&#xff1a; 部署数据库服务MySQL、部署共享存储NFS、配置网站服务、测试配置 一、项目拓扑结构 PROJECT1回顾&#xff1a; PROJECT2-DAY1拓扑&#xff1a; 服务器IP及角色规划&#xff1a; 主机名 IP地址 角色 mysql11 192.168.4.11 MySQL数据库服务器 m…

人工智能 | 手工测试用例转Web自动化测试生成

简介 在传统编写 Web 自动化测试用例的过程中&#xff0c;基本都是需要测试工程师&#xff0c;根据功能测试用例转换为自动化测试的用例。市面上自动生成 Web 或 App 自动化测试用例的产品无非也都是通过录制的方式&#xff0c;获取操作人的行为操作&#xff0c;从而记录测试用…

游戏盾SDK真的能无视攻击吗

游戏盾SDK真的能无视攻击吗&#xff1f;在当今的互联网环境中&#xff0c;游戏行业蓬勃发展&#xff0c;但同时也面临着日益严峻的安全挑战。DDoS攻击、CC攻击、外挂作弊等恶意行为频发&#xff0c;不仅威胁着游戏的稳定性和公平性&#xff0c;也严重影响了玩家的游戏体验。为了…

Google Adsense账号被封怎么办?

海外营销广告通常依赖Google AdSense作为一种流行方法来获得流量。但是&#xff0c;如果您不小心&#xff0c;您的 AdSense 帐户可能会被禁止&#xff0c;让您失去创收的途径。下面我们将总结Google AdSense 帐户被封的常见原因原因以及如何解决此问题。 一、Google AdSense账号…

通信工程学习:什么是VIM虚拟化基础设施管理器

VIM:虚拟化基础设施管理器 VIM(Virtualized Infrastructure Manager)虚拟化基础设施管理器,是一种负责管理和控制虚拟化环境中所有虚拟资源的工具和系统。以下是关于VIM虚拟化基础设施管理器的详细解释: 一、定义与功能 VIM是网络功能虚拟化(NFV)架构中…

[EBPF] 实时捕获DM数据库是否存在SQL阻塞

1. 介绍 eBPF&#xff08;extened Berkeley Packet Filter&#xff09;是一种内核技术&#xff0c;它允许开发人员在不修改内核代码的情况下运行特定的功能。eBPF 的概念源自于 Berkeley Packet Filter&#xff08;BPF&#xff09;&#xff0c;后者是由贝尔实验室开发的一种网…

如何用Python监控本股市的方法

引言 1.1 Python在量化交易中的应用 在金融科技的浪潮中&#xff0c;Python已经成为量化交易领域的一把利器。无论是数据分析、策略开发还是回测优化&#xff0c;Python都能提供强大的支持。其丰富的第三方库&#xff0c;如pandas、numpy、matplotlib和backtrader&#xff0c…

Python知识点:如何使用Flink与Python进行实时数据处理

开篇&#xff0c;先说一个好消息&#xff0c;截止到2025年1月1日前&#xff0c;翻到文末找到我&#xff0c;赠送定制版的开题报告和任务书&#xff0c;先到先得&#xff01;过期不候&#xff01; 如何使用Flink与Python进行实时数据处理 Apache Flink是一个流处理框架&#xf…