As a mature programming language, Java naturally has a number of ways to solve time problems. Sometimes we are not familiar with some of the built-in Apis of Java, and we are not familiar with a certain scenario, which leads to a difficult problem. Like in this scenario daylight saving time and winter time

Daylight saving time and winter time

Time zone transitions are absolutely necessary for global functionality. In general, using timestamps and Java’s built-in apis solves 99% of the problems, but when it comes to daylight saving time or winter time, the problem may not be so easy.

Let’s start with daylight saving time and winter time: basically, some countries in the world change their time zone on a certain date, and then change it back at a certain time, either daylight saving time or winter time

Note: You can use a search engine to find out more about this concept. Instead of using someone else’s interpretation of daylight saving time, which means moving the clock forward an hour, I use the concept of changing the time zone for the sake of the following explanation

Daylight saving time and winter time business scenarios

For example, if a country with daylight saving time and winter time has a summer event from 11:00 to 1:00 for seven days, and those seven days fall on the day when the time changes, what’s the problem?

The difference between 12:20 on the preceding day and 12:20 on the following day is not 24 hours, because the time change carries with it a change in the time zone. Because the time zone changes, the same 12:20 corresponds to a different number of milliseconds (there is no time zone problem for milliseconds).

So the seven-day process can’t be handled simply with +24 hours, because it could result in 11 to 1 before the break and 12 to 2 after the break

How to solve

Java provides a nifty API, TimeZone, that deals specifically with time zones

There are two API

TimeZone itemTimeZone = timezone. getTimeZone(TimeZone name); itemTimeZone.getOffset(long data); / / display the current time zone and 0 time zone offset, and make the relevant itemTimeZone. GetRawOffset (); // Displays the offset of the current time zone and 0 time zone, regardless of the time systemCopy the code

This makes it easy. If the two apis return different values, it means that the current time is in one or the other

Take it a step further and solve the above requirement by ensuring that the date is +1 when spanning time

To explain this requirement, go straight to the most basic example

I used the time zone of Spanish country to do a +24 hour day iteration, theoretically should make 2019-10-26 4pm and 6pm, become 2019-10-27 4pm and 6pm, but because of the problem of daylight saving time, actually become 2019-10-27 3pm and 5pm

Run the following code

long oneData = 24*60*60*1000;
/ / the 2019-10-26 04:00:00
long startTime = 1572055200000L;
/ / the 2019-10-26 06:00:00
long endTime = 1572062400000L;
SimpleDateFormat bjSdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
TimeZone timeZone = TimeZone.getTimeZone("Europe/Madrid");
bjSdf.setTimeZone(timeZone);
System.out.println(bjSdf.format(new Date(startTime)));
System.out.println(bjSdf.format(new Date(endTime)));
System.out.println(bjSdf.format(new Date(startTime+oneData)));
System.out.println(bjSdf.format(new Date(endTime+oneData)));
Copy the code

Output:

// Cross DAYLIGHT saving time has a problem.... The 2019-10-27 03:00:00 2019-10-27 05:00:00Copy the code

So you can’t do that, you can just go to the code, and it’s actually a very simple algorithm


public class ScopeTimeDO {
    // Start time
    private Long startTime;
    // End time
    private Long endTime;
    // The number of cycles, the number of days the activity lasts
    private Integer cycleCount;
}

/ * * * *@paramScopeTimeDO Activity time data *@paramTimeZeno Time zone information such as "Europe/Madrid" *@returnReturns a millisecond time series of activities constructed based on the number of days of duration */
public List<long[]> createTimeInterval(ScopeTimeDO scopeTimeDO,String timeZeno) {
    long startTime = scopeTimeDO.getStartTime();
    long endTime = scopeTimeDO.getEndTime();
    int cycleCount = scopeTimeDO.getCycleCount();
    int speed = 0;
    TimeZone itemTimeZone = TimeZone.getTimeZone(timeZeno);
    List<long[]> timeList = new ArrayList<>();
    while (cycleCount >=TIME_SCOPE_CYCLE_COUNT_DEFAULT_VALUE) {
        long[] item = new long[2];
        if(speed==0){
            item[0] = startTime;
            item[1] = endTime;
            speed = 1;
        }else{
            long[] last = timeList.get(timeList.size()-1);
            long beforeStartP = itemTimeZone.getOffset(last[0]);
            long beforeEndP = itemTimeZone.getOffset(last[1]);
            item[0] = last[0]+DAY;
            item[1] = last[1]+DAY;
            long nowStartP = itemTimeZone.getOffset(item[0]);
            long nowEndP = itemTimeZone.getOffset(item[1]);
            item[0] = item[0] + (beforeStartP-nowStartP);
            item[1] = item[1] + (beforeEndP-nowEndP);
        }
        cycleCount--;
        timeList.add(item);
    }
    return timeList;
}
Copy the code

The above algorithm simply compensates for the time difference, comparing the current time with the later time, and if there is a difference + the gap on the line, so as to ensure that the time is uniform across daylight saving time