如何获得当前的一周和一个月的第一天?

我有几个事件的date以毫秒为单位 [1],我想知道哪些事件是在本周内和本月内,但我不知道如何获得第一天(日/月/年)运行一周,并将其转换为毫秒,这与本月的第一天相同。

[1]Since January 1, 1970, 00:00:00 GMT 

本周以毫秒为单位:

 // get today and clear time of day Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, 0); // ! clear would not reset the hour of day ! cal.clear(Calendar.MINUTE); cal.clear(Calendar.SECOND); cal.clear(Calendar.MILLISECOND); // get start of this week in milliseconds cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek()); System.out.println("Start of this week: " + cal.getTime()); System.out.println("... in milliseconds: " + cal.getTimeInMillis()); // start of the next week cal.add(Calendar.WEEK_OF_YEAR, 1); System.out.println("Start of the next week: " + cal.getTime()); System.out.println("... in milliseconds: " + cal.getTimeInMillis()); 

本月以毫秒为单位:

 // get today and clear time of day Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, 0); // ! clear would not reset the hour of day ! cal.clear(Calendar.MINUTE); cal.clear(Calendar.SECOND); cal.clear(Calendar.MILLISECOND); // get start of the month cal.set(Calendar.DAY_OF_MONTH, 1); System.out.println("Start of the month: " + cal.getTime()); System.out.println("... in milliseconds: " + cal.getTimeInMillis()); // get start of the next month cal.add(Calendar.MONTH, 1); System.out.println("Start of the next month: " + cal.getTime()); System.out.println("... in milliseconds: " + cal.getTimeInMillis()); 

一周的第一天可以通过java.util.Calendar帮助确定如下:

 Calendar calendar = Calendar.getInstance(); calendar.clear(); calendar.setTimeInMillis(timestamp); while (calendar.get(Calendar.DAY_OF_WEEK) > calendar.getFirstDayOfWeek()) { calendar.add(Calendar.DATE, -1); // Substract 1 day until first day of week. } long firstDayOfWeekTimestamp = calendar.getTimeInMillis(); 

一个月的第一天可以确定如下:

 Calendar calendar = Calendar.getInstance(); calendar.clear(); calendar.setTimeInMillis(timestamp); while (calendar.get(Calendar.DATE) > 1) { calendar.add(Calendar.DATE, -1); // Substract 1 day until first day of month. } long firstDayOfMonthTimestamp = calendar.getTimeInMillis(); 

相当详细,是的。


Java 7将会有一个大大改进的date和时间API( JSR-310 )。 如果你还不能切换,那么你可以使用JodaTime ,这使得它更简单:

 DateTime dateTime = new DateTime(timestamp); long firstDayOfWeekTimestamp = dateTime.withDayOfWeek(1).getMillis(); 

 DateTime dateTime = new DateTime(timestamp); long firstDayOfMonthTimestamp = dateTime.withDayOfMonth(1).getMillis(); 

注意!

 while (calendar.get(Calendar.DAY_OF_WEEK) > calendar.getFirstDayOfWeek()) { calendar.add(Calendar.DATE, -1); // Substract 1 day until first day of week. } 

是个好主意,但是有一些问题:例如,我来自乌克兰,而我国的calendar.getFirstDayOfWeek()是2(星期一)。 今天是1(星期天)。 在这种情况下,calendar.add没有被调用。

所以,正确的方法是将“>”更改为“!=”:

 while (calendar.get(Calendar.DAY_OF_WEEK) != calendar.getFirstDayOfWeek()) {... 

java.time

Java 8及更高版本中的java.time框架取代了旧的java.util.Date/.Calendar类。 老class级certificate是麻烦的,混乱的,有缺陷的。 避免他们。

java.time框架的灵感来自由JSR 310定义的高度成功的Joda-Time库,由ThreeTen-Extra项目扩展,并在教程中进行了解释。

Instant

Instant类表示UTC时间轴上的一个时刻。

java.time框架的分辨率为纳秒,即9位小数秒。 毫秒仅为小数秒的3位数字。 因为毫秒分辨率是常见的,所以java.time包含一个方便的工厂方法。

 long millisecondsSinceEpoch = 1446959825213L; Instant instant = Instant.ofEpochMilli ( millisecondsSinceEpoch ); 

毫秒自年月:1446959825213即时:2015-11-08T05:17:05.213Z

ZonedDateTime

考虑当前周和当前月份,我们需要应用特定的时区。

 ZoneId zoneId = ZoneId.of ( "America/Montreal" ); ZonedDateTime zdt = ZonedDateTime.ofInstant ( instant , zoneId ); 

在zoneId:America / Montreal即:2015-11-08T00:17:05.213-05:00 [America / Montreal]

半开

在date工作中,我们通常使用半开式方法来定义一段时间。 开始是包容性的,而在排他性的结局。 而不是试图确定一周(或一个月)的最后一秒钟,我们得到一周(或月)的第一时刻。 所以一个星期从星期一的第一个时刻开始,一直到下个星期一的第一个时刻。

让我们一周的第一天,最后一天。 java.time框架包含一个工具, with方法和ChronoField枚举。

默认情况下,java.time使用ISO 8601标准。 所以星期一是一周的第一天(1),星期天是最后一天(7)。

 ZonedDateTime firstOfWeek = zdt.with ( ChronoField.DAY_OF_WEEK , 1 ); // ISO 8601, Monday is first day of week. ZonedDateTime firstOfNextWeek = firstOfWeek.plusWeeks ( 1 ); 

那一周从2015-11-02T00:17:05.213-05:00 [America / Montreal]到2015-11-09T00:17:05.213-05:00 [America / Montreal]

哎呀! 查看这些值的时间。 我们想要一天中的第一个时刻。 由于夏令时(DST)或其他exception情况,一天中的第一个时刻并不总是为00:00:00.000 。 所以我们应该让java.time代表我们进行调整。 要做到这一点,我们必须通过LocalDate类。

 ZonedDateTime firstOfWeek = zdt.with ( ChronoField.DAY_OF_WEEK , 1 ); // ISO 8601, Monday is first day of week. firstOfWeek = firstOfWeek.toLocalDate ().atStartOfDay ( zoneId ); ZonedDateTime firstOfNextWeek = firstOfWeek.plusWeeks ( 1 ); 

那一周从2015-11-02T00:00-05:00 [America / Montreal]到2015-11-09T00:00-05:00 [America / Montreal]

同样的月份。

 ZonedDateTime firstOfMonth = zdt.with ( ChronoField.DAY_OF_MONTH , 1 ); firstOfMonth = firstOfMonth.toLocalDate ().atStartOfDay ( zoneId ); ZonedDateTime firstOfNextMonth = firstOfMonth.plusMonths ( 1 ); 

那个月从2015-11-01T00:00-04:00 [America / Montreal]到2015-12-01T00:00-05:00 [America / Montreal]

YearMonth

另一种查看是否有同一个月的时刻是同一个月的方法是检查相同的YearMonth值。

例如,假设thisZdtthatZdt都是ZonedDateTime对象:

 boolean inSameMonth = YearMonth.from( thisZdt ).equals( YearMonth.from( thatZdt ) ) ; 

毫秒

我强烈build议不要以毫秒为单位进行date和时间的工作。 这确实是date时间课程倾向于在内部工作的方式,但是我们有类的理由。 处理从时期计数是笨拙的,因为这些值是人类无法理解的,所以debugging和logging很困难且容易出错。 而且,正如我们已经看到的,不同的解决scheme可能正在起作用。 旧的Java类和Joda-Time库使用毫秒,而像Postgres这样的数据库使用微秒,现在java.time使用纳秒。

你会把文本当作位处理,还是让像StringStringBufferStringBuilder这样的类来处理这些细节?

但是如果你坚持,从ZonedDateTime得到一个Instant ,并从那里得到一个毫秒数的时代。 但请记住, 这个调用可能意味着数据丢失ZonedDateTime / Instant可能存在的任何微秒或纳秒将被截断(丢失)。

 long millis = firstOfWeek.toInstant().toEpochMilli(); // Possible data loss. 

要获得月份的第一天,只需获取Date ,并将当前Date设置为当月的第一天。 如果需要,可以清除小时,分钟,秒和毫秒。

 private static Date firstDayOfMonth(Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.set(Calendar.DATE, 1); return calendar.getTime(); } 

本周的第一天是相同的事情,但使用Calendar.DAY_OF_WEEK代替

 private static Date firstDayOfWeek(Date date) { Calendar calendar = Calendar.getInstance(); calendar.setTime(date); calendar.set(Calendar.DAY_OF_WEEK, 1); return calendar.getTime(); } 

在这种情况下:

 // get today and clear time of day Calendar cal = Calendar.getInstance(); cal.clear(Calendar.HOUR_OF_DAY); <---- is the current hour not 0 hour cal.clear(Calendar.MINUTE); cal.clear(Calendar.SECOND); cal.clear(Calendar.MILLISECOND); 

所以Calendar.HOUR_OF_DAY返回8,9,12,15,18作为当前运行小时。 我认为会更好地改变这样的路线:

 c.set(Calendar.HOUR_OF_DAY,0); 

这样的一天总是从0小时开始

您应该能够将您的号码转换为Java日历,例如:

  Calendar.getInstance().setTimeInMillis(myDate); 

从那里,比较不应该太难。

 import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.GregorianCalendar; import java.util.Scanner; /** This Program will display day for, 1st and last days in a given month and year @author Manoj Kumar Dunna Mail Id : manojdunna@gmail.com */ public class DayOfWeek { public static void main(String[] args) { String strDate = null; int year = 0, month = 0; Scanner sc = new Scanner(System.in); System.out.print("Enter YYYY/MM: "); strDate = sc.next(); Calendar cal = new GregorianCalendar(); String [] date = strDate.split("/"); year = Integer.parseInt(date[0]); month = Integer.parseInt(date[1]); cal.set(year, month-1, 1); System.out.println(new SimpleDateFormat("EEEE").format(cal.getTime())); cal.add(Calendar.MONTH, 1); cal.add(Calendar.DAY_OF_YEAR, -1); System.out.println(new SimpleDateFormat("EEEE").format(cal.getTime())); } } 
 Simple Solution: package com.util.calendarutil; import java.text.DateFormat; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.Calendar; import java.util.Date; import java.util.GregorianCalendar; public class CalUtil { public static void main(String args[]){ DateFormat df = new SimpleDateFormat("dd/mm/yyyy"); Date dt = null; try { dt = df.parse("23/01/2016"); } catch (ParseException e) { System.out.println("Error"); } Calendar cal = Calendar.getInstance(); cal.setTime(dt); cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek()); Date startDate = cal.getTime(); cal.add(Calendar.DATE, 6); Date endDate = cal.getTime(); System.out.println("Start Date:"+startDate+"End Date:"+endDate); } } 

我为此创build了一些方法:

 public static String catchLastDayOfCurrentWeek(String pattern) { Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, 0); cal.clear(Calendar.MINUTE); cal.clear(Calendar.SECOND); cal.clear(Calendar.MILLISECOND); cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek()); return calendarToString(cal, pattern); } public static String catchLastDayOfCurrentWeek(String pattern) { Calendar cal = Calendar.getInstance(); cal.set(Calendar.HOUR_OF_DAY, 0); cal.clear(Calendar.MINUTE); cal.clear(Calendar.SECOND); cal.clear(Calendar.MILLISECOND); cal.set(Calendar.DAY_OF_WEEK, cal.getFirstDayOfWeek()); cal.add(Calendar.WEEK_OF_YEAR, 1); cal.add(Calendar.MILLISECOND, -1); return calendarToString(cal, pattern); } public static String catchTheFirstDayOfThemonth(Integer month, pattern padrao) { Calendar cal = GregorianCalendar.getInstance(); cal.setTime(new Date()); cal.set(Calendar.MONTH, month); cal.set(Calendar.DAY_OF_MONTH, 1); return calendarToString(cal, pattern); } public static String catchTheLastDayOfThemonth(Integer month, String pattern) { Calendar cal = GregorianCalendar.getInstance(); cal.setTime(new Date()); cal.set(cal.get(Calendar.YEAR), month, cal.getActualMaximum(Calendar.DAY_OF_MONTH)); return calendarToString(cal, pattern); } public static String calendarToString(Calendar calendar, String pattern) { if (calendar == null) { return ""; } SimpleDateFormat format = new SimpleDateFormat(pattern, LocaleUtils.DEFAULT_LOCALE); return format.format(calendar.getTime()); } 

你可以在这里看到更多。

 public static void main(String[] args) { System.out.println(getMonthlyEpochList(1498867199L,12,"Monthly")); } public static Map<String,String> getMonthlyEpochList(Long currentEpoch, int noOfTerms, String timeMode) { Map<String,String> map = new LinkedHashMap<String,String>(); int month = 0; while(noOfTerms != 0) { Calendar calendar = Calendar.getInstance(); calendar.add(Calendar.MONTH, month); calendar.set(Calendar.DATE, calendar.getActualMinimum(Calendar.DAY_OF_MONTH)); Date monthFirstDay = calendar.getTime(); calendar.set(Calendar.DATE, calendar.getActualMaximum(Calendar.DAY_OF_MONTH)); Date monthLastDay = calendar.getTime(); map.put(getMMYY(monthFirstDay.getTime()), monthFirstDay + ":" +monthLastDay); month--; noOfTerms--; } return map; }