正如@Ole V.V.所解释的,您需要定义一周从哪一天开始,以及第一周必须考虑的天数。
例如,ISO-8601标准考虑:
该月分为多个时段,每个时段从一周中定义的第一天开始。如果当月最早的时间段少于最小天数,则称为周0
,如果至少有最小天数,则称为周1
。
根据你如何定义它们,你可以得到不同的结果。考虑2017年7月的日历:
July 2017
Su Mo Tu We Th Fr Sa
1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31
如果我们考虑ISO的定义,我们有:
如果我们将一周的第一天视为周日,将第一周的最小天数视为1,则我们有:
由于日历的解决方案已经发布,我将使用新的API编写一个解决方案。如果您使用的是Java8,请考虑使用新的Java。时间API。与旧的API相比,它更容易实现,更少出现错误,更不容易出错。
如果你用Java
下面的代码适用于这两种情况。唯一的区别是包名(在Java8中是
Java.time
),而在ThreeTen Backport(或Android的ThreeTenABP)中是org。三十。bp
),但类和方法名称相同。
我使用的是
DateTimeFormatter
,因为它包含所有字段(月、年、周和月的周),并相应地解析日期,创建一个LocalDate
(其中包含日/月/年字段)。我还使用了WeekFields
类,它可以配置为使用不同的周定义(第一周的第一天和最小天数)
还有一点调整,将周日视为零:
public LocalDate getDate(int weekOfMonth, int dayOfWeek, int month, int year) {
// you can customize your week definition (first day of week and mininum days in first week)
WeekFields wf = WeekFields.of(DayOfWeek.SUNDAY, 2);
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
// week of month, using week definition from WeekFields
.appendValue(wf.weekOfMonth()).appendPattern(" ")
// day of week
.appendValue(ChronoField.DAY_OF_WEEK)
// month and year
.appendPattern(" M/yyyy")
// create formatter
.toFormatter();
return LocalDate.parse(weekOfMonth + " " +
// Sunday is 0, adjusting value
(dayOfWeek == 0 ? 7 : dayOfWeek) + " " + month + "/" + year, fmt);
}
使用此代码(一周从周日开始,需要将2天视为第一周,否则,如上面第一个示例所示,一周将为零):
LocalDate d = getDate(1, 6, 7, 2017);
d
将于2017年7月8日(2017年7月1日星期六)举行。
如果要使用ISO 8601定义,请使用常量
WeekFields. ISO
而不是使用WeekFields.of()
方法。
正如@Ole V.V.在评论中所建议的,也可以在不创建格式化程序的情况下完成:获取当月的第一个
dayOfWeek
,并将其调整到所需的weekOfMonth
:
public LocalDate getDate(int weekOfMonth, int dayOfWeek, int month, int year) {
// you can customize your week definition (first day of week and mininum days in first week)
WeekFields wf = WeekFields.of(DayOfWeek.SUNDAY, 2);
// Sunday is 0, adjusting value
DayOfWeek dow = DayOfWeek.of(dayOfWeek == 0 ? 7 : dayOfWeek);
// get the first weekday of the month
LocalDate first = LocalDate.of(year, month, 1).with(TemporalAdjusters.nextOrSame(dow));
// check in which week this date is
int week = first.get(wf.weekOfMonth());
// adjust to weekOfMonth
return first.plusWeeks(weekOfMonth - week);
}
这种方法的工作原理完全相同,但不需要格式化程序——我用1600年到2100年的数据进行了测试,得到了相同的结果。
PS:
Calendar
也通过方法setFirstDayOfWeek()
和setMinimalDaysInFirstWeek()
具有类似的配置。您可以通过调用相应的get
方法来检查默认配置。
要从年份、周数和星期几创建日期,请使用java.util.Calendar
实例:
Calendar cal = Calendar.getInstance();
cal.set(Calendar.YEAR, 2017);
cal.set(Calendar.WEEK_OF_YEAR, 26);
cal.set(Calendar.DAY_OF_WEEK, Calendar.MONDAY);
从日历
转换为java。util。日期
:
Date date = cal.getTime();
将Date
转换为java。时间LocalDateTime
使用:
LocalDateTime localDateTime = LocalDateTime.ofInstant(date.toInstant(), ZoneId.systemDefault());
尽管你有标签,我同意Joe C的评论,但你应该更喜欢现代Java日期和时间API(又名java.time
或JSR-310),而不是早已过时的Calendar
和朋友。现代类对程序员更友好,使用起来更友好,它们带来的惊喜更少,导致更清晰、更自然的代码(至少在你习惯流畅的风格时),并且在你犯错误时更容易调试。
我不知道你是如何计算每个月的周数的,我假设第一周从月初开始,持续7天(所以第二周从8号开始,第5周从29号开始),如果你的计算方式不同,请看雨果的回答。
我建议这种方法:
public static LocalDate weekNoAndDayToDate(Year year, Month month, int weekOfMonth, int dayOfWeek) {
// find day of week: convert from 0 (Sunday) to 6 (Saturday)
// to DayOfWeek, from 1 (Monday) to 7 (Sunday)
DayOfWeek dow;
if (dayOfWeek == 0) { // Sunday
dow = DayOfWeek.SUNDAY;
} else {
dow = DayOfWeek.of(dayOfWeek);
}
return year.atMonth(month)
.atDay(1)
.with(TemporalAdjusters.nextOrSame(dow))
.with(ChronoField.ALIGNED_WEEK_OF_MONTH, weekOfMonth);
}
例如,我们可以这样做
LocalDate today = weekNoAndDayToDate(Year.of(2017), Month.JULY, 1, 1);
这就产生了
2017-07-03
如果您需要Date
或GregorianCalendar
,例如对于您无法更改的旧API,请执行以下操作之一:
Date oldfashiondDateObject
= Date.from(today.atStartOfDay(ZoneId.systemDefault()).toInstant());
GregorianCalendar oldfashionedCalendarObject
= GregorianCalendar.from(today.atStartOfDay(ZoneId.systemDefault()));
在这两种情况下,结果在不同的时区会有所不同(这是旧课程固有的问题之一)。在我的电脑上,第一个生成日期
Mon Jul 03 00:00:00 CEST 2017
第二个生成一个gregorianalendar
等于同一时间点。
如何通过给出一个月中的一周和一周中的一天来获得日期。 示例:如果我需要2018年11月的第三个星期二。 月周:3,周日:3 预计日期:2018年11月20日 但我们得到的价值是:2018年11月13日。因为本月的开始日(星期四)少于预期的日期(星期二)。 我怎样才能得到正确的日期??
在我的android应用程序中,我正在努力获取提供日期的周数。但是它没有给我正确的周数,我正在使用下面的代码来获取周数。 从上述日历中可以看出,截至2016年1月,属于第1周的天数只有第1、第2和第3天。第二周的相关天数为第四、第五、第六、第七、第八、第九和第十天。第三周的相关天数为11、12、13、14、15、16和17日,依此类推。但对于2016年1月12日,上述代码给出了第2周,而不是第3周
问题内容: 我想查找给定月份中的所有星期六和星期日。我该怎么办? 问题答案: 在 最简单 的方法是只迭代所有在一个月的日子里,检查一周的某一天为他们每个人。例如: 我 绝对可以确定 ,这样做的方式要高效得多-但这就是我的出发点,当发现速度太慢时进行优化。 请注意,如果您能够使用Joda Time,那将使您的生活更加轻松…
如何分类?例如,我希望一周的第一天是星期一。由此: 周一至周二周三至周五周六 我想要这个: 星期一至星期二星期三星期五星期六至星期日 或者我希望我一周的第一天是周五 那么在输出中应该是这样的: 星期五星期六星期一星期二星期三星期四
我正在尝试为我们的财务部门生成一些代码,他们需要一个字段,该字段将为他们提供一年中的当前一周,但以星期天为基础,这是一周的第一天。例如01-25-16(MM dd yyyy)将是第4周。然而,当我尝试使用和
问题内容: 我目前正在使用vbscript函数以2/12/2009格式获取本周和上周的第一天值。我想知道是否可以使用SQL查询。 问题答案: 这些语句应该在TSQL中完成您想要的操作。请注意,这些报表基于当前日期。您可以将getdate()替换为所需的任何日期: