吸取教训:一段网上找的代码突然爆了,项目出现大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 += 365;
}
} return timeDistance + (day2-day1) ;
}
else //不同年
{
System.out.println("判断day2 - day1 : " + (day2-day1));
return day2-day1;
}
}
代码来源:https://www.cnblogs.com/0201zcr/p/5000977.html
把代码复制到项目里,调试下,发现没问题就直接用了,毕竟谷歌结果第一名,放心。
这段代码跑了几个月一直没问题,但是到了2020-1-1日那天,有玩家反馈收到了几百封奖励邮件,高兴坏了,但是出于对游戏的热爱,还是通知了运营人员。
运营把bug反馈到服务器这边后我开始排查,百思不得其解的是最近几天都没有更新服务器, 而前几天服务器都稳稳地,怎么突然就出BUG了呢。
接下来就是分析玩家数据,结合代码逻辑确定问题所在,最终根据BUG的表现排除了所有可能性后,发现唯一可能出问题的地方就是那个网上复制过来的计算天数差的函数。
根据调试发现,这个函数在两个日期参数是不同的年份并且第一个日期大于第二个日期的时候,会返回一个错误的结果
比如
differentDays("2020-1-1","2019-12-25")
理论上这么调用正确的结果是 -7,但是因为函数有bug,调用结果是 358
于是本来不用发奖励,因为这种特殊情况一下子发出去358份,严重影响了游戏某类道具的平衡性。
至于补救方式就是统计名单,把发出去但还没有用掉的道具回收,用掉的就当福利,然后再发公告道歉,再送些其他物品弥补。
也幸好补救的及时,要是这些道具收不回来,游戏运营的策略都要大变了,我特么肯定没好果子吃了。
所以千万别在网上复制来路不明的代码乱用,如果真的要用,必须反复测试,否则哪一天突然暴雷有你受的。
改用Java8的日期库修复了BUG
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;
}
吸取教训:一段网上找的代码突然爆了,项目出现大BUG的更多相关文章
- 完全图解scrollLeft,scrollWidth,clientWidth,offsetWidth 获取相对途径,滚动图片(网上找的,未经试验,但觉得比较好)
获取元素的位置属性可以通过 HTMLElement.offsetLeft HTMLElement.offsetTop 但是,这两个属性所储存的数值并不是该元素相对整个浏览器画布的绝对位置,而是相对于其 ...
- 分享一段Java搞笑的代码注释
今天在群里看到有人分享了一段搞笑的注释代码,觉得挺好玩的,在这里收藏一下 // _ooOoo_ // o8888888o // 88" . "88 // (| -_- |) // ...
- 从网上找的 visual studio 的各个版本下载地址,vs2010/vs2012/vs2013带注册码
从网上找的 visual studio 的各个版本下载地址,很全,从 6.0 一直 到 vs2013,要的拿去吧... Microsoft Visual Studio 6.0 下载:英文版360云盘下 ...
- PeopleSoft底层表,闪存查找历史代码(不小心改)
Oracle 闪存查找历史代码 select * from (SELECT * FROM PSPCMTXT AS OF TIMESTAMP to_timestamp('20180725 1 ...
- 内存布局:栈,堆,BSS段(静态区),代码段,数据段
简介 我们程序运行的时候都是放在内存里的.根据静态.成员函数.代码段.对象.等等.放在不同的内存分块里.大概分为5块 1 栈 2 堆 3 BSS段-全局区-(静态区) 4 代码段 5 数据段 栈 ...
- 数据段描述符和代码段描述符(二)——《x86汇编语言:从实模式到保护模式》读书笔记11
这篇博文,我们编写一个C语言的小程序,来解析数据段或者代码段描述符的各个字段.这样我们阅读原书的代码就会方便一点,只要运行这个小程序,就可以明白程序中定义的数据段或者代码段的描述符了. 这段代码,我用 ...
- 数据段描述符和代码段描述符(一)——《x86汇编语言:从实模式到保护模式》读书笔记10
一.段描述符的分类 在上一篇博文中已经说过,为了使用段,我们必须要创建段描述符.80X86中有各种各样的段描述符,下图展示了它们的分类. 看了上图,你也许会说:天啊,怎么这么多段描述符啊!我可怎么记住 ...
- 将这段美化的css代码
很多时候如果不是用了很多样式,很难把边框修饰得好看,看了一篇博文,觉得真的挺漂亮,也挺好看. 转载的博文地址 将这段美化的css代码 border:1px solid #96c2f1;backgrou ...
- C#代码反编译 得到项目可运行源码
C#代码反编译 得到项目可运行源码 摘自:http://www.cnblogs.com/know/archive/2011/03/15/1985026.html 谈到"C#代码反编译&quo ...
随机推荐
- Acegi框架介绍
开发四年只会写业务代码,分布式高并发都不会还做程序员?->>> 概述 对于任何一个完整的应用系 统,完善的认证和授权机制是必不可少的.Acegi Securit ...
- linux Completions 机制
内核编程的一个普通模式包括在当前线程之外初始化某个动作, 接着等待这个动作结束. 这个动作可能是创建一个新内核线程或者用户空间进程, 对一个存在着的进程的请求, 或 者一些基于硬件的动作. 在这些情况 ...
- 第3本:Visual Studio程序员箴言
第3本:Visual Studio程序员箴言 Visual Studio 2010是我经常使用的程序开发工具,也知道VS中有大量的快捷键可以帮助提高效率,可惜就是不愿意记忆,最近在学vim的时候快速把 ...
- 【75.28%】【codeforces 764B】Decoding
time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...
- JavaSE基础---异常
异常 Throwable----具备可拋性:就是该体系中的类和对象都可以被关键字throw或throws所操作. |---Error ---错误,一般不编写针对性处理方式 |---Exception- ...
- sqlyog提示:没有执行查询。请在 SQL 窗口中输入查询或将光标放在一个查询上。
以下内容纯属猜测: sqlyog 在执行输入的sql语句时,对已经执行过的语句,是不会再执行的,所以出现这个问题,很可能是sql语句没有修改,就试图执行第二遍.
- SQL语句之子语句
子语句之间的顺序: WHERE GROUP ORDER LIMIT
- Java 学习笔记(11)——异常处理
异常是程序中的一些错误,但并不是所有的错误都是异常,并且错误有时候是可以避免的. 比如说,你的代码少了一个分号,那么运行出来结果是提示是错误 java.lang.Error:如果你用System.ou ...
- Visual Studio Team Services使用教程【5】:Readers tfs组成员添加
2017.4.23之后建议朋友看下面的帖子 TFS2017 & VSTS 实战(繁体中文视频) Visual Studio Team Services(VSTS)与敏捷开发ALM实战关键报告( ...
- To learns
1. avro https://www.jianshu.com/p/ecbb607809c4