Click “like” to see, form a habit, the public account search [dime technology] pay attention to more original technical articles. This article has been included in GitHub org_Hejianhui /JavaStudy.

preface

Last week, there was a dynamic calculation period when making a product requirement (for example, now it is 13:00, then the time period is 15:10-17:10, 17:10-19:10, 19:10-21:10; Is the earliest departure time parameters for the current time + h10min [2], the latest time for the start time at the end of the 20 o ‘clock time period after 20 points), extensive use of the date/time during class libraries, in line with the familiar date time class library to this article, finally I will put my how to implement the requirements of an algorithm to stick out.

Time class library in JDK8 prior

1.1 Defects and deficiencies of the original time inventory

All of our pre-Java8 libraries have had trouble dealing with date-time, including but not limited to the following slots:

In Java version 1.0, the manipulation of time and date is entirely dependent on the java.util.Data class, which can only represent time in milliseconds, not dates.

  • There is a big flaw in ease of use, with the year starting from 1900 and the month starting from 0.
  • The toString method returns an unintuitive value with a time zone.

In Java1.1, many methods in many Date classes were deprecated and java.util.calendar was added. But like Date, the Calendar classes have similar problems and design flaws that make code written using them error-prone.

  • The months are still going to start at 0.
  • Common Date and time operations need to use Date, Canendar, and SimpleDateFormat at the same time, which is complicated.
  • Part feature exists only in a certain class (parsing and formatting the DateFormat method of futures time exists only in the Date class).
  • DateFormat is not thread-safe, and if two threads try to parse dates using the same Formatter, they may get unexpected results.
  • Date and Canendar are mutable.

1.2 Reasons why SimpleDateFormat thread is unsafe

Since the contributed calendar variable used by the Parse method is not thread-safe. Calendar is assigned in the format (subFormat) method, which is worth processing in parse. Therefore, in the case of concurrency, calendar is not cleaned in time and values are overwritten.

/**
 * The {@link Calendar} instance used for calculating the date-time fields
 * and the instant of time. This field is used for both formatting and
 * parsing.
 *  
 * <p>Subclasses should initialize this field to a {@link Calendar}
 * appropriate for the {@link Locale} associated with this
 * <code>DateFormat</code>.
 * @serial* /
protected Calendar calendar;

@Override
public StringBuffer format(Date date, StringBuffer toAppendTo, FieldPosition pos){
    pos.beginIndex = pos.endIndex = 0;
    return format(date, toAppendTo, pos.getFieldDelegate());
}

// Called from Format after creating a FieldDelegate
private StringBuffer format(Date date, StringBuffer toAppendTo, FieldDelegate delegate) {
    // Convert input date to time field list
    calendar.setTime(date);

	// At this point the fields of Calendar have been set. Calendar
	// will fill in default values for missing fields when the time
	// is computed.

	pos.index = start;

	Date parsedDate;
	try {
        parsedDate = calb.establish(calendar).getTime();
        // If the year value is ambiguous,
        // then the two-digit year == the default start year
        if (ambiguousYear[0]) {
            if (parsedDate.before(defaultCenturyStart)) {
                parsedDate = calb.addYear(100).establish(calendar).getTime(); }}}}Copy the code

1.3 How do I Solve the thread Insecurity problem?

  1. Create a thread-exclusive SimpleDateFormat variable for each thread using ThreadLocal;
  2. Create local variables as needed;
  3. Use org.apacle.com mons. Lang3. Time. DateFormatUtils
  4. Using joda-time (described below)

Joda-time date-time class library

2.1 introduction

Joda-time is a quality date and Time development library provided by Joda that follows the Apache2.0 open source protocol in addition to the JDK.

Joda: Joda-money: Joda-beans: Joda-convert: Joda-collect: Joda-collect: Joda-collect: Joda-money: Joda-beans: Joda-convert: Joda-collect: Joda-collect: Joda-money: Joda-beans: Joda-convert: Joda-collect: Joda-collect

2.1.1 Why is Joda-time used

  1. Ease of use: Calendar is difficult to access “normal” dates and lacks simple anticorrosions, while Joda-time has simple field access, such as getting the year’sgetYear()And get the day of the weekgetDayOfWeek() 。
  2. Easy to extend: The JDK supports implementing multiple calendar systems by using subclasses, but this is cumbersome, and it is difficult to implement another calendar system first. Joda-time supports based onChronologyClass to implement multiple pluggable calendar systems.
  3. Full-featured: Joda-time provides all the necessary functionality for date and Time calculations, and it provides out-of-the-box features.
  4. Up-to-date time zone calculations: Time zone implementations are based on a common time zone information database, updated several times a year. The new version of Joda-Time includes all changes to this database, and the necessary updates should be made as soon as possible, as it is easy to update the zone data manually.
  5. Calendar support: Provides 8 calendar systems.
  6. Interoperability: Internal identification using milliseconds is consistent with the JDK or other common time representations.
  7. Good performance: Supports minimal computation for all domains accessed.
  8. Good test coverage: a full range of testers to ensure the quality of the library,
  9. Complete documentation: There is a complete user guide, which provides an overview and covers common usage scenarios. Javadoc is very detailed and covers the rest of the API.
  10. Development: actively developed since 2002, is a mature and reliable codebase, some related projects are also currently available.
  11. Open Source: Released under the Apache 2.0 open source license.

2.1.2 Key advantages of joda-time

  1. LocalDate: contains only the date
  2. LocalTime: contains only the time
  3. Instant: a point in time on the timeline
  4. DateTime: The complete date and time in the time zone
  5. DateTimeZone: Better time zone
  6. Duration and Period: indicates the Duration of time
  7. Interval: indicates the time between two time points
  8. Comprehensive and flexible time formatting and conversion

Because joda-time has so many advantages over the pre-Java8 Time libraries, joda-time has become the de facto standard Java date and Time library.

2.2 Feature Interpretation

2.2.1 Joda-time and JDK interoperability

Interoperability is the ability of the Joda class to generate instances of java.util.date (and Calendar), which allows us to retain our existing JDK dependencies while using Joda to handle complex Date/time calculations.

Date To Joda-Time

Date date = new Date();
DateTime dateTime = new DateTime(date);
Copy the code

Canendar To Joda-Time

Calendar calendar = Calendar.getInstance();
DateTime dateTime = new DateTime(calendar);
Copy the code

Joda-Time To Date

Date date = new Date();  
DateTime dateTime = new DateTime(date);                       
Date date2 = dateTime.toDate();
Copy the code

Joda-Time To Calendar

Calendar calendar = Calendar.getInstance();  
dateTime = new DateTime(calendar);  
Calendar calendar2 = dateTime.toCalendar(Locale.CHINA); 
Copy the code

2.2.2 Understanding of key date/time concepts of Joda

Joda uses the following concepts to make them applicable to any date/time library:

Immutability

Joda-time is similar to java.lang.String in that their instances cannot be modified (because any operation that changes their value generates a new object), which also means that they are thread-safe.

Instant

Such as interface org. Joda. Time. In the ReadableInstant suggests, Instant represents a precise point in time, from the epoch: 1970-01-0t00:00:00 Z The number of milliseconds to start counting, which is also designed so that subclasses are compatible with JDK Date and Calendar classes.

/**
 * Defines an instant in the datetime continuum.
 * This interface expresses the datetime as milliseconds from 1970-01-01T00:00:00Z.
 * <p>
 * The implementation of this interface may be mutable or immutable.
 * This interface only gives access to retrieve data, never to change it.
 * <p>
 * Methods in your application should be defined using <code>ReadableInstant</code>
 * as a parameter if the method only wants to read the instant without needing to know
 * the specific datetime fields.
 * <p>
 * The {@codeCompareTo} method is no longer defined in this class in version 2.0. * Instead, the definition is simply inherited from the {@codeComparable} interface. * This approach is necessary to preserve binary compatibility. * The definition of the comparison  is ascending order by millisecond instant. * Implementors are recommended to extend {@code AbstractInstant} instead of this interface.
 *
 * @author Stephen Colebourne
 * @since1.0 * /
public interface ReadableInstant extends Comparable<ReadableInstant> {

    /**
     * Get the value as the number of milliseconds since
     * the epoch, 1970-01-01T00:00:00Z.
     *
     * @return the value as milliseconds
     */
    long getMillis(a); ......}Copy the code

The DateTime class inheritance diagram looks like this:

Partial

Temporality represents an exact moment in time relative to the epoch, while a local time refers to a fragment of time that can be changed (essentially generating new classes) in some way, so that it can be used in multiple places as a point in a repeating cycle.

Chronology

The core of the design of Joda-time is the Chronology (org.joda.time.chronology). Fundamentally, the Chronology is a calendar system, a special way to calculate Time, and a framework to execute the calendar algorithm in it. The chronology of the eight types supported by joda-time is as follows:

  • ISO (the default) – org. Joda. Time. Chrono. ISOChronology
  • GJ – org.joda.time.chrono.GJChronology
  • Gregorian – org.joda.time.chrono.GregorianChronology
  • Julian – org.joda.time.chrono.JulianChronology
  • Coptic – org.joda.time.chrono.CopticChronology
  • Buddhist – org.joda.time.chrono.BuddhistChronology
  • Ethiopic – org.joda.time.chrono.EthiopicChronology
  • Islamic – org.joda.time.chrono.IslamicChronology

Each of the above chronologies can be used as a computing engine for a particular calendar system and is pluggable implementation.

Time Zone

Specific definition see an explanation, in the actual encoding any strict Time calculations must be involved in the process of Time zone (or relative to GMT), Joda – Time of the corresponding core classes for org. Joda. Time. DateTimeZone, although everyday in use process, pair is involved in operation, But how the DateTimeZone affects DateTime is worth noting and won’t be covered here.

2.3 Specific usage method

Joda-time: Joda-time: joda-time: Joda-time: Joda-time: Joda-time

2.3.1 Creating a Joda-time Object

Momentariness – ReadableInstant

// 1. Use system time
DateTime dateTime1 = new DateTime();
// 2. Use date in JDK
Date jdkDate1 = new Date();
DateTime dateTime2 = new DateTime(jdkDate1);
// 3. Specify milliseconds
Date jdkDate2 = new Date();
long millis = jdkDate.getTime();
DateTime dateTime3 = new DateTime(millis);
// 4. Use Calendar
Calendar calendar = Calendar.getInstance();
DateTime dateTime4 = new DateTime(calendar);
// 5. Specify a moment (partial time segment) with multiple fields
// year month day hour(midnight is zero) minute second milliseconds
DateTime dateTime5 = new DateTime(2000.1.1.0.0.0.0);
// 6. Generate a DateTime from another DateTime
DateTime dateTime6 = new DateTime(dateTime1);
// 7. Generate DateTime with time string
String timeString = "2019-01-01T00:00:00-06:00";
DateTime dateTime7 = DateTime.parse(timeString);
Copy the code

Local – the ReadablePartial

You can create a local time when the date or time you are dealing with in your program does not need to be a full moment, such as if you just want to focus on the year/month/day, or the time of day, or the day of the week. Joda Time – has said the Time is org. Joda Time. The ReadablePartial interface, realize its two classes LocalDate and LocalTime is respectively used to denote year/month/day and a Time of day.

// Explicitly provide each of the contained fields
LocalDate localDate = new LocalDate(2019.1.1);
// 6:30:06 PM
LocalTime localTime = new LocalTime(18.30.6.0);
Copy the code

LocalDate is replaced early Joda – Time version used in the org. Joda. Time. YearMonthDay, LocalTime is an early version of the org. Alternative. Joda Time. TimeOfDay. (all have been marked as outdated).

The time span

Joda-time provides three classes for representing Time spans (which can be useful in some business requirements).

  • Duration

This class represents absolute precision in milliseconds and provides standard mathematical conversions while converting time spans to standard units.

  • Period

This class representation is expressed in years, months and days.

  • Interval

This class represents a specific time span and defines the scope of the time span with an explicit moment. Interval is a half-open Interval, so the time span encapsulated by Interval includes the start of the period but not the end of the period.

2.3.2 Using the joda-time method to process the Time

DateTime today = new DateTime();
// Get the time before 777 seconds
DateTime dateTime1 = today.minus(777 * 1000);
// Get the time for tomorrow
DateTime tomorrow = today.plusDays(1);
// Get the date of the first day of the month
DateTime dateTime2 = today.withDayOfMonth(1); 
// Get the last day of the month three months after the current time
DateTime dateTime3 = today.plusMonths(3).dayOfMonth().withMaximumValue();
Copy the code

The following is a partial list of DateTime methods: Methods starting with plus/minus (plusDay, minusMonths, for example) : used to return instances that have been added or subtracted from a DateTime instance

  1. Plus (long duration) increments the specified number of milliseconds and returns

  2. PlusYears (int years) Adds the specified year and returns

  3. PlusMonths (int months) Adds the specified month and returns the value

  4. PlusWeeks (int weeks) adds the specified week and returns

  5. PlusDays (int days) Adds the specified number of days and returns the value

  6. PlusHours (int hours) increments the specified hour and returns

  7. PlusMinutes (int minutes) Increments the specified minute and returns

  8. PlusSeconds (int seconds) Increments the specified number of seconds and returns

  9. PlusMillis (int millis) increments the specified millisecond and returns

On the contrary, the prefix plus is an increase and minus is a decrease

The with method is used to return the DateTime instance after the specified date unit has been updated

  1. WithCenturyOfEra (int centuryOfEra) Updates time century units and returns
  2. WithYearOfCentury (int yearOfCentury) Updates century year and returns
  3. WithYear (int year) Updates the time year and returns
  4. WithWeekyear (int weekyear) Update week and return
  5. WithMonthOfYear (int monthOfYear) Updates the month and returns
  6. WithDayOfYear (int dayOfYear) Updates the number of days and returns
  7. WithDayOfMonth (int dayOfMonth) Updates the number of days and returns
  8. WithDayOfWeek (int dayOfWeek) Number of days in which the update time is returned
  9. WithHourOfDay (int hour) Update time hour and returns
  10. WithMinuteOfHour (int minute) Specifies the update minute and returns
  11. WithSecondOfMinute (int second) Update time in seconds and returns
  12. Withmillisedersecond (int millis) returns the millisedersecond
  13. Withmillisederday (int millis) updates time in milliseconds and returns
  14. WithTimeAtStartOfDay () gets the earliest time of the day

Some operations to determine the size state of a DateTime object

  1. CompareTo (DateTime d) to compare two time size is greater than the specified time return 1 time less than a specified time return 1 equal returns 0
  2. Equals (DateTime d) compares whether two times are equal
  3. IsAfter (Long Instant) Checks whether the time is longer than the specified time
  4. IsAfterNow () checks whether the time is greater than the current time
  5. IsBefore (Long Instant) Checks whether the time is shorter than the specified time
  6. IsBeforeNow () Checks whether the time is smaller than the current time
  7. IsEqual (long instant) checks whether the time isEqual to the specified time
  8. IsEqualNow () checks whether the time is equal to the current time

2.3.3 Format the Time in joda-time mode

// The format template passed in only needs a format string compatible with JDK SimpleDateFormat
public static String convert(Date date,String dateFormat){
    return new DateTime(date).toString(dateFormat);
}
// Convert Date in JDK to DateTime in UTC time zone
DateTime dateTime = new DateTime(new Date(), DateTimeZone.UTC);
// Convert String to DateTime
public static Date convertUTC2Date(String utcDate){
    DateTime dateTime =DateTime.parse(utcDate, DateTimeFormat.forPattern("yyyy-MM-dd'T'HH:mm:ss.SSSZ"));
    return dateTime.toDate();
 }

Copy the code

Please refer to the official documentation for more information.

New time class library in JAVA 8

3.1 introduction

Due to the flaws and poor experience of previous JDK versions, and the influence of what has become the de facto standard joda-time, Oracle decided to provide high-quality date and Time support in the JAVA API. This is the new Time library in JDK 8 that incorporates most of the joda-time features. The authors of Joda-time were actually involved in the development and implemented all of JSR310. The new API is located under Java.time. Common classes include LocalDate, LocalTime, Instant, Duration, and Period.

Because the new Time library in JDK 8 borrowed a lot from the design and naming of Joda-time, if you’re a joda-time user, you can use the new API with no cost to learn (there are a few differences to note, of course).

3.2 Usage

3.2.1 Using LocalDate and LocalTime

The first is LocalDate. An instance of this class is an immutable object that provides a simple date with no information about the time of the day. Also, it doesn’t come with any time zone information.

// Create LocalDate with the specified date
LocalDate date = LocalDate.of(2019.1.1);
// Get the current date
LocalDate today = LocalDate.now();
// Get today's attributes
int year = date.getYear();
Month month = date.getMonth();
int day = date.getDayOfMonth();
DayOfWeek dow = date.getDayOfWeek();
int len = date.lengthOfMonth();
boolean leap = date.isLeapYear();
// Obtain the required attribute fields from the enumerated value of ChronoField
int year = date.get(ChronoField.YEAR);
Copy the code

Then there’s LocalTime, which represents a certain time of day.

LocalTime time = LocalTime.of(18.18.18);
int hour = time.getHour();
int minute = time.getMinute();
int second = time.getSecond();
Copy the code

Both LocalDate and LocalTime can be created by using the static method parse to parse the string.

LocalDate date = LocalDate.parse("2019-01-01");

LocalTime time = LocalTime.parse("18:18:18");
Copy the code

You can also pass a DateTimeFormatter to the parse method, an instance of which defines how to format a date or time object. It is a replacement for the older java.util.dateformat.

3.2.2 LocalDateTime

// Create LocalDateTime directly
LocalDateTime dt1 = LocalDateTime.of(2019, Month.JANUARY, 1.18.18.18);
// Merge the date and time
LocalDate date = LocalDate.parse("2019-01-01");
LocalTime time = LocalTime.parse("18:18:18");
LocalDateTime dt2 = LocalDateTime.of(date, time);
LocalDateTime dt3 = date.atTime(18.18.18);
LocalDateTime dt4 = date.atTime(time);
LocalDateTime dt5 = time.atDate(date);
// Extract LocalDate or LocalTime from LocalDateTime
LocalDate date1 = dt1.toLocalDate();
LocalTime time1 = dt1.toLocalTime();
Copy the code

3.3.3 Instant

The Instant class is designed to be understood by computers and represents a single large integer at a point in time that is actually computed in seconds (in nanoseconds) since the first Unix year (traditionally midnight on January 1, 1970, the UTC time zone).

// Pass an instance of the class that has been created in seconds
Instant.ofEpochSecond(3);
// Pass the number of seconds + nanoseconds after 2 seconds plus 1 million nanoseconds (1 second)
Instant.ofEpochSecond(2.1 _000_000_000);
Copy the code

3.3.4 Duration and Period

Duration is used to compare the time difference between two LocalTime objects or two Instant.

Duration d1 = Duration.between(time1, time2);
Duration d1 = Duration.between(dateTime1, dateTime2);
Duration d2 = Duration.between(instant1, instant2);
Copy the code

Period is used to compare multiple times in terms of years, months and days.

Period tenDays = Period.between(LocalDate.of(2019.1.1), lcalDate.of(2019.2.2));
Copy the code

Of course, both the Duration and Period classes provide a number of very convenient factory classes to create instances of directly.

Duration threeMinutes = Duration.ofMinutes(3);
Duration threeMinutes = Duration.of(3, ChronoUnit.MINUTES);
Period tenDays = Period.ofDays(10);
Period threeWeeks = Period.ofWeeks(3);
Period twoYearsSixMonthsOneDay = Period.of(2.6.1);
Copy the code

3.3.5 Manipulating, parsing, and formatting dates

// Use the withAttribute method directly
LocalDate date1 = LocalDate.of(2019.1.1);
LocalDate date2 = date1.withYear(2019);
LocalDate date3 = date2.withDayOfMonth(1);
LocalDate date4 = date3.with(ChronoField.MONTH_OF_YEAR, 1);
Copy the code

All the classes declaring Temporal interface LocalDate, LocalTime, LocalDateTime and Instant, they all use get and with methods to distinguish the reading and modification of object value. If unsupported fields are used to access fields, Throws a UnsupportedTemporalTypeException anomalies. Similarly, the plus and minus methods are declared in the Temporal interface. By using these methods, adding or subtracting a number to TemporalUnit object, we can very conveniently move the Temporal object back or back to a certain time period. Through ChronoUnit enumeration, we can very conveniently implement the TemporalUnit interface.

3.3.6 More customized processing time

Pass a customized TemporalAdjuster object to the overloaded WITH method for more flexibility with dates. The Time and date API already provides a number of predefined TemporalAdjuster, which can be accessed through the Static factory method of the TemporalAdjuster class. The names of these methods are very intuitive, and the method name is the problem description. In some cases, if you need to define your own TemporalAdjuster, just declare the TemporalAdjuster interface and implement the corresponding method yourself.

LocalDate date1 = LocalDate.of(2014.3.18);
LocalDate date2 = date1.with(TemporalAdjuster.nextOrSame(DayOfWeek.SUNDAY));
LocalDate date3 = date2.with(TemporalAdjuster.lastDayOfMonth());
Copy the code

3.3.7 Parsing a date-time Object

Formatting and parsing date-time objects is another very important function in our daily work, and the new java.time.format package is designed specifically for this purpose. Of these, the most important class is the DateTimeFormatter. All instances of DateTimeFormatter can be used to create a string representing a particular date or time in a certain format. (All DateTimeFormatter instances are thread-safe in contrast to the old java.util.dateformat)

// Use different formatters to generate strings
LocalDate date = LocalDate.of(2019.1.1);
String s1 = date.format(DateTimeFormatter.BASIC_ISO_DATE);
String s2 = date.format(DateTimeFormatter.ISO_LOCAL_DATE);
// Generate a LocalDate object
LocalDate date1 = LocalDate.parse("20190101", DateTimeFormatter.BASIC_ISO_DATE);
LocalDate date2 = LocalDate.parse("2019-01-01", DateTimeFormatter.ISO_LOCAL_DATE);
Copy the code
// Create a formatter with a specific schema
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("dd/MM/yyyy");
LocalDate date1 = LocalDate.of(2019.1.1);
String formattedDate = date1.format(formatter);
LocalDate date2 = LocalDate.parse(formattedDate, formatter);
Copy the code

3.3.8 Handling different time zones and calendar systems

In the new date-time library, a new java.time.ZoneId class (which, like other date and time classes, cannot be modified) replaces the java.util.TimeZone in order to minimize the complexity of dealing with time zones. A time zone is a region divided into the same standard time interval according to certain rules. The ZoneRules class contains 40 such instances. You can getRules for a specific time zone simply by calling getRules() of ZoneId. Each particular ZoneId object is identified by a region ID in the format {region}/{city}. Such as:

ZoneId romeZone = ZoneId.of("Asia/Shanghai");
Copy the code

Java 8 added a new method toZoneId to the original TimeZone, which converts an old TimeZone object to a ZoneId:

ZoneId zoneId = TimeZone.getDefault().toZoneId();
Copy the code

The resulting ZoneId object can be combined with LocalDate, LocalDateTime, or Instant to construct an instance of ZonedDateTime that represents a point in time relative to the specified time zone:

LocalDate date = LocalDate.of(2019, Month.JANUARY, 1);
ZonedDateTime zdt1 = date.atStartOfDay(romeZone);
LocalDateTime dateTime = LocalDateTime.of(2019, Month.JANUARY, 18.13.45);
ZonedDateTime zdt2 = dateTime.atZone(romeZone);
Instant instant = Instant.now();
ZonedDateTime zdt3 = instant.atZone(romeZone);
Copy the code

With ZoneId, you can also convert LocalDateTime to Instant:

LocalDateTime dateTime = LocalDateTime.of(2019, Month.JANUARY, 18.13.45);
Instant instantFromDateTime = dateTime.toInstant(romeZone);
Copy the code

You can also get the LocalDateTime object in reverse:

Instant instant = Instant.now();
LocalDateTime timeFromInstant = LocalDateTime.ofInstant(instant, romeZone);
Copy the code

Unlike joda-time, the date-time library in Java8 provides four other calendar systems, each of which has a corresponding logging class, They are ThaiBuddhistDate, MinguoDate, JapaneseDate and HijrahDate. All of these classes, as well as LocalDate, implement the ChronoLocalDate interface to model dates in the Gregorian calendar. With the LocalDate object, you can create instances of these classes. Also, using the static factory methods they provide, you can create instances of any Temporal object.

LocalDate date = LocalDate.of(2019, Month.JANUARY, 1);
JapaneseDate japaneseDate = JapaneseDate.from(date);
Copy the code

The resources

Joda-time introduces the Joda Time project and the java8 Time API

Dynamic computing time

Requirements: if it is 13:00, the time period is 15:10-17:10, 17:10-19:10, 19:10-21:10; That is, the earliest departure time is the current time + parameter [2h10min], and the latest time is the time when the start time is before 20:00 and the end time is after 20:00). How many time periods are there in total?

Analysis:

  1. Start time of the first time range: current time + parameter [2h10min], the intermediate time range is 2h;
  2. By understanding that the latest time range is a time range that starts before 20:00 and ends after 20:00, we can assume that the maximum time variable is Max
  3. Assuming that the current time is now and there are n periods in total, the formula can be derived:now + (2h * n) + 10min  <= max;

Note: all calculations are converted to milliseconds

public class Test {
    / / ms
    static final long slot = 130 * 60 * 1000;

    private static List<TimeSelectItem> buildStartEndTime(Long now, Long max) {
        // now + (2h * n) + 10min <= max;

        Long n = (max - now - 60 * 1000)/(120 * 60 * 1000);
        System.out.println("max:" + max);
        System.out.println("now:" + now);
        System.out.println(" max - now:" + (max - now));
        System.out.println("n:" + n);

        List<TimeSelectItem> timeSelectItems = new ArrayList<>();

        Long startTimestamp = now + slot;
        Long endTimestamp = startTimestamp + 120 * 60 * 1000;

        for (int i = 1; i <= n; i++) {
            // Start time
            // startTimestamp = startTimestamp + i * (120 * 60 * 1000);
            // End time
            endTimestamp = startTimestamp + (120 * 60 * 1000);

            System.out.println(startTimestamp);
            System.out.println(endTimestamp);

            TimeSelectItem item = new TimeSelectItem();

            DateTime dt = new DateTime(startTimestamp);
            int hour = dt.hourOfDay().get();
            int millis = dt.getMinuteOfHour();
            String startTag = hour + ":" + millis;

            DateTime dt1 = new DateTime(endTimestamp);
            int hour1 = dt1.hourOfDay().get();
            long millis1 = dt1.getMinuteOfHour();
            String enTag = hour1 + ":" + millis1;

            item.setDisplayName(startTag + "-" + enTag);

            item.setStartTimestamp(startTimestamp);
            item.setEndTimestamp(endTimestamp);
            timeSelectItems.add(item);

            startTimestamp = endTimestamp;
        }
        return timeSelectItems;
    }

    public static void main(String[] args) {
        Long start = DateTime.now().getMillis();
        Calendar c = Calendar.getInstance();
        c.setTime(new Date());
        c.set(Calendar.HOUR_OF_DAY, 20);
        c.set(Calendar.MINUTE, 0);
        c.set(Calendar.SECOND, 0);


        DateTime dt = new DateTime();
        dt.withHourOfDay(20);
        Long end = c.getTimeInMillis();
       
        // List<TimeSelectItem> list = buildStartEndTime(1614747600000L, 1614772800000L);
        List<TimeSelectItem> list = buildStartEndTime(1614834000000L, end);
        for(TimeSelectItem item : list ) { System.out.println(item); }}}Copy the code

GitHub Org_Hejianhui /JavaStudy GitHub Hejianhui /JavaStudy