简体   繁体   English

在Java中生成两个日期之间的日开始时间和日结束时间。 夏时制问题

[英]Generate Day start and Day end time between two dates in Java. Day light saving issue

I have to generate days between two two dates. 我必须在两个日期之间生成日期。 for ex: 例如:

1420090495000 -> Jan 1, 2015 1420090495000-> 2015年1月1日

1430458495000 -> May 1, 2015 1430458495000-> 2015年5月1日

I have to generate timestamps for all days like 我必须像整天一样生成时间戳

Jan 1, 2015 00:00:00 - Jan 1, 2015 23:59:59 2015年1月1日00:00:00-2015年1月1日23:59:59

Jan 2, 2015 00:00:00 - Jan 2, 2015 23:59:59 2015年1月2日00:00:00-2015年1月2日23:59:59

Jan 3, 2015 00:00:00 - Jan 3, 2015 23:59:59 2015年1月3日00:00:00-2015年1月3日23:59:59

so on 依此类推

I am able to do that. 我能够做到。 But I am getting some problem with day light saving issue. 但是我在日光节约问题上遇到了一些问题。 On march somewhere it is generating like this 3月某个地方,它像这样生成

Mar 8, 2015 00:00:00 - Mar 9, 2015 00:01:00 Which is wrong and it should be like Mar 8, 2015 00:00:00 - Mar 8, 2015 23:59:59 2015年3月8日00:00:00-2015年3月9日00:01:00错了,应该像2015年3月8日00:00:00-2015年3月8日23:59:59

I found it because of day light saving issue. 我发现它是由于日光节约问题。 How to solve this issue ? 如何解决这个问题?

My code is: 我的代码是:

public static List<String> getDatesRange(long start, long end, String tzOffset) {
//tzOffset is 420. for USA

        TimeZone tz = TimeZone.getTimeZone(tzOffset);

        List<String> dates=new ArrayList();
        Calendar calendar = Calendar.getInstance(tz);

        calendar.set(Calendar.DAY_OF_WEEK, 1);
        calendar.set(Calendar.HOUR, 0);
        calendar.set(Calendar.MINUTE, 0);
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MILLISECOND, 0);


        while (start<end) {
            calendar.setTimeInMillis(start);
            long startTime = calendar.getTimeInMillis();
            int year= calendar.getWeekYear();


            long endTime = start + (1 * 24 * 3600 * 1000L);

            if(endTime<end) {
                endTime-=1000;
                System.out.println("Start Date= " + new Date(new Timestamp(start).getTime())+" ("+startTime+"), End Date= "+new Date(new Timestamp(endTime).getTime())+"("+endTime+")");

dates.add(startTime+"-"+endTime);
                start= endTime+1000;
            }
            else{
                System.out.println("Start Date= " + new Date(new Timestamp(start).getTime()) + " (" + startTime + "), End Date= " + new Date(new Timestamp(end).getTime()) + "(" + end + ")");
                start=end;
                dates.add(startTime+"-"+end);
            }
        }
        return dates;
    }

The problem is that you want to print dates without the notion of time zones (although the start dates depends on the tzOffset argument). 问题是您要打印不带时区概念的日期(尽管开始日期取决于tzOffset参数)。 If you use Java 8, the new Java time API has a class specifically designed for that: LocalDate . 如果使用Java 8,则新的Java时间API具有专门为此设计的类: LocalDate

So your method can be done by first determining the start and end day based on the timestamp and the time zone then get rid of all time zone considerations. 因此,可以通过首先根据时间戳和时区确定开始和结束日期,然后摆脱所有时区注意事项来完成您的方法。 And to print the range you can "cheat" by hardcoding the start/end time in the formatter. 要打印范围,您可以通过在格式化程序中对开始/结束时间进行硬编码来“作弊”。

public static List<String> getDatesRange(long start, long end, String tzOffsetMinutes) {
  Instant startInstant = Instant.ofEpochMilli(start);
  Instant endInstant = Instant.ofEpochMilli(end);

  int offsetSeconds = Integer.parseInt(tzOffsetMinutes) * 60;
  ZoneOffset offset = ZoneOffset.ofTotalSeconds(offsetSeconds);
  LocalDate startDate = OffsetDateTime.ofInstant(startInstant, offset).toLocalDate();
  LocalDate endDate = OffsetDateTime.ofInstant(endInstant, offset).toLocalDate();

  List<String> dates = new ArrayList<> ();
  DateTimeFormatter fmt = DateTimeFormatter.ofPattern(
                                         "MMM d, yyyy 00:00:00 - MMM d, yyyy 23:59:59");

  for (LocalDate d = startDate; !d.isAfter(endDate); d = d.plusDays(1)) {
    dates.add(fmt.format(d));
  }
  return dates;
}

You can probably do something similar with Calendars. 您可能可以对日历执行类似的操作。

There are a couple things I wonder about this: 我对此有些疑问:

  • Why use Longs to define dates? 为什么要使用Longs定义日期?
  • Why return a list of Strings instead of a list of Dates? 为什么要返回字符串列表而不是日期列表?
  • Why take the timezone into consideration at all in a case like this? 在这种情况下,为什么要完全考虑时区?

Nevertheless, you can achieve this simply using Calendar and SimpleDateFormat , like this: 不过,您可以使用Calendar和SimpleDateFormat轻松实现此目的,如下所示:

public static Calendar getDayStart(final long timeInMillis) {
    final Calendar cal = Calendar.getInstance();
    // end time as a date
    cal.setTimeInMillis(timeInMillis);

    cal.set(Calendar.HOUR, 0);
    cal.set(Calendar.MINUTE, 0);
    cal.set(Calendar.SECOND, 0);
    cal.set(Calendar.MILLISECOND, 0);

    return cal;
}

public static List<String> getDatesRange(final long start, final long end) {

    final Calendar cal = getDayStart(start);
    final Date startDate = cal.getTime();

    final Calendar calEnd = getDayStart(end);
    //adding one day because of the strict comparison in the while below
    calEnd.add(Calendar.DAY_OF_YEAR, 1);
    final Date endDate = calEnd.getTime();

    final SimpleDateFormat formatter = new SimpleDateFormat("MMM d, yyyy HH:mm:ss");

    final List<String> dates = new ArrayList<String>();
    final Date dayEnd;
    String currentDay = "";

    while(cal.getTime().before(endDate)) {
        currentDay = formatter.format(cal.getTime());
        currentDay += " - ";
        //going to the end of the day
        cal.add(Calendar.DAY_OF_YEAR, 1);
        cal.add(Calendar.SECOND, -1);
        currentDay += formatter.format(cal.getTime());
        //going to next day again and continue the loop
        cal.add(Calendar.SECOND, 1);
        //add what we computed to the list of days
        dates.add(currentDay);
    }

    return dates;
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM