跳到主要内容
极客日志极客日志面向AI+效率的开发者社区
首页博客我的书AI学习GitHub 精选镜像AI工具UI配色美学关于
搜索内容 / 工具 / 仓库 / 镜像...⌘K搜索
注册
博客列表
Javajava算法

Java 日期差计算函数 Bug 导致游戏道具异常发放

游戏服务器开发中需计算玩家离线天数以发放道具。开发者直接采用网络搜索的 Java 日期差计算函数,该函数在跨年且起始时间晚于结束时间时返回错误结果(如 2020-01-01 与 2019-12-25 相差 358 天而非 -7 天)。此 Bug 导致特定日期大量误发道具,影响游戏平衡。最终通过 Java 8 本地日期库 LocalDate 和 ChronoUnit 修复了计算逻辑。案例警示复制外部代码需谨慎测试,避免生产环境突发故障。

ApiHolic发布于 2020/3/13更新于 2026/10/2380 浏览
Java 日期差计算函数 Bug 导致游戏道具异常发放

游戏服务器开发中曾遇到一个需求,给符合某些要求的玩家发送道具奖励,奖励的数量根据离线的天数计算。

该需求实现逻辑简单,只需要在玩家上线的时候计算上次离线时间和当前时间间隔的天数,然后根据策划的算法,计算出道具种类与数量,发一封邮件给玩家就可以了。

由于缺乏现成函数,搜索获取了一段代码,代码如下:

public static int differentDays(Date date1, Date date2) {
    Calendar cal1 = Calendar.getInstance();
    cal1.setTime(date1);
    Calendar cal2 = Calendar.getInstance();
    cal2.setTime(date2);
    int day1 = cal1.get(Calendar.DAY_OF_YEAR);
    int day2 = cal2.get(Calendar.DAY_OF_YEAR);
    int year1 = cal1.get(Calendar.YEAR);
    int year2 = cal2.get(Calendar.YEAR);
    if (year1 != year2) {
        // 同一年
        int timeDistance = 0;
        for (int i = year1; i < year2; i++) {
            if (i % 4 == 0 && i % 100 != 0 || i % 400 == 0) {
                // 闰年
                timeDistance += 366;
            } else {
                // 不是闰年
                timeDistance += ;
            }
        }
         timeDistance + (day2 - day1);
    }  {
        
        System.out.println( + (day2 - day1));
         day2 - day1;
    }
}
365
return
else
// 不同年
"判断 day2 - day1 : "
return

把代码复制到项目里,调试下,发现没问题就直接用了。

这段代码跑了几个月一直没问题,但是到了 2020-01-01 那天,有玩家反馈收到了几百封奖励邮件。运营把 Bug 反馈到服务器这边后开始排查,近期无更新,问题突现。

接下来就是分析玩家数据,结合代码逻辑确定问题所在,最终根据 Bug 的表现排除了所有可能性后,发现唯一可能出问题的地方就是那个网上复制过来的计算天数差的函数。

根据调试发现,这个函数在两个日期参数是不同的年份并且第一个日期大于第二个日期的时候,会返回一个错误的结果,比如:

differentDays("2020-1-1", "2019-12-25")

理论上这么调用正确的结果是 -7,但是因为函数有 Bug,调用结果是 358。

于是本来不用发奖励,因为这种特殊情况一下子发出去 358 份,严重影响了游戏某类道具的平衡性。

修复方案采用 Java 8 的日期库,代码如下:

public static int differentDays(Date date1, Date date2) {
    if (date1 == null || date2 == null) {
        throw new RuntimeException("日期不能为空");
    }
    LocalDate localDate1 = date2LocalDate(date1);
    LocalDate localDate2 = date2LocalDate(date2);
    return Generic.long2int(localDate1.until(localDate2, ChronoUnit.DAYS));
}

public static LocalDate date2LocalDate(Date date) {
    Instant instant = date.toInstant();
    ZoneId zoneId = ZoneId.systemDefault();
    LocalDate localDate = instant.atZone(zoneId).toLocalDate();
    return localDate;
}

后续处理包括统计名单,把发出去但还没有用掉的道具回收,用掉的就当福利,然后再发公告道歉,再送些其他物品弥补。

建议不要随意使用未经验证的代码,如果真的要用,必须反复测试,否则哪一天突然暴雷有你受的。

更多推荐文章

查看全部
  • MySQL 免安装版 Windows 部署配置指南
  • VSCode 中通过扩展使用 OpenAI 兼容模型配置 GitHub Copilot
  • Zotero 8.0.1 英文文献批量下载与自动化管理实战
  • 大模型提示工程实战指南:掌握提问驱动 AI
  • 链表十大经典 OJ 题目详解与实战技巧
  • 深度视觉赋予足式机器人极限运动能力:从盲行到跑酷
  • 通义万相 2.1 多模态生成模型部署与应用实践
  • Python 网络爬虫技术详解
  • Java 异常处理:从原理到实战最佳实践
  • .NET 集成 GoView 低代码可视化大屏实战指南
  • 前端动画演进:告别 jQuery animate,拥抱现代方案
  • Python 汽车销售大屏数据分析可视化系统设计与实现
  • 使用 OpenClaw 集成飞书构建专属 AI 机器人指南
  • GitHub Copilot 学生身份认证与激活指南
  • 前端 EME DRM 反录屏原理与实战代码
  • Python 开发必备十大工具:从 IDE 到数据分析库详解
  • Proxmox VE 部署 Kali Linux 完整实战指南
  • openKylin 通过 SSH+cpolar 实现远程内网穿透
  • 基于 Unity 与 AI 工具快速开发简易小游戏
  • 如何确保大模型 RAG 生成的信息基于可靠数据源

相关免费在线工具

  • Keycode 信息

    查找任何按下的键的javascript键代码、代码、位置和修饰符。 在线工具,Keycode 信息在线工具,online

  • Escape 与 Native 编解码

    JavaScript 字符串转义/反转义;Java 风格 \uXXXX(Native2Ascii)编码与解码。 在线工具,Escape 与 Native 编解码在线工具,online

  • JavaScript / HTML 格式化

    使用 Prettier 在浏览器内格式化 JavaScript 或 HTML 片段。 在线工具,JavaScript / HTML 格式化在线工具,online

  • JavaScript 压缩与混淆

    Terser 压缩、变量名混淆,或 javascript-obfuscator 高强度混淆(体积会增大)。 在线工具,JavaScript 压缩与混淆在线工具,online

  • 加密/解密文本

    使用加密算法(如AES、TripleDES、Rabbit或RC4)加密和解密文本明文。 在线工具,加密/解密文本在线工具,online

  • Gemini 图片去水印

    基于开源反向 Alpha 混合算法去除 Gemini/Nano Banana 图片水印,支持批量处理与下载。 在线工具,Gemini 图片去水印在线工具,online