Why a Simple Date‑Difference Function Broke My Game Server and How to Fix It

A game server bug caused hundreds of reward emails to be sent on New Year's Day because a copied Java date‑difference function returned incorrect values for cross‑year dates, and the issue was resolved by replacing it with a reliable Java 8 time API implementation.

Java Backend Technology
Java Backend Technology
Java Backend Technology
Why a Simple Date‑Difference Function Broke My Game Server and How to Fix It

The author, a game server developer, needed to award offline players based on the number of days they were away. The logic required calculating the day difference between the last offline time and the current login time.

Instead of writing the calculation, the author copied a Java function from the web that used Calendar to compute the difference. The function worked for months but failed when the two dates spanned different years and the first date was later than the second.

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; // leap year
            } else {
                timeDistance += 365; // common year
            }
        }
        return timeDistance + (day2 - day1);
    } else {
        System.out.println("判断day2 - day1 : " + (day2 - day1));
        return day2 - day1;
    }
}

On 2020‑01‑01 the function returned 358 days for the call differentDays("2020-1-1", "2019-12-25"), where the correct result should be –7. This caused the system to send hundreds of reward emails, breaking game balance.

To fix the bug, the author rewrote the method using Java 8's java.time API, which handles leap years and cross‑year calculations correctly.

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;
}

After deploying the corrected code, the erroneous reward distribution stopped. The author also recovered the mistakenly sent items, apologized to players, and emphasized the importance of testing any third‑party code before using it in production.

Original Source

Signed-in readers can open the original source through BestHub's protected redirect.

Sign in to view source
Republication Notice

This article has been distilled and summarized from source material, then republished for learning and reference. If you believe it infringes your rights, please contactadmin@besthub.devand we will review it promptly.

Java8bug-fixgame servercode-reviewdate-timedatetime-api
Java Backend Technology
Written by

Java Backend Technology

Focus on Java-related technologies: SSM, Spring ecosystem, microservices, MySQL, MyCat, clustering, distributed systems, middleware, Linux, networking, multithreading. Occasionally cover DevOps tools like Jenkins, Nexus, Docker, and ELK. Also share technical insights from time to time, committed to Java full-stack development!

0 followers
Reader feedback

How this landed with the community

Sign in to like

Rate this article

Was this worth your time?

Sign in to rate
Discussion

0 Comments

Thoughtful readers leave field notes, pushback, and hard-won operational detail here.