繁体   English   中英

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

[英]How to get the first day of the current week and month?

我有几个事件的日期以毫秒[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 将带有一个大大改进的日期和时间 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();

时间

Java 8 及更高版本中的java.time框架取代了旧的 java.util.Date/.Calendar 类。 旧的类已被证明是麻烦、混乱和有缺陷的。 避开它们。

java.time 框架的灵感来自非常成功的Joda-Time库,该库由JSR 310定义,由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]

半开

在日期时间工作中,我们通常使用半开放方法来定义时间跨度。 开头是包容的,而结尾是独占的 我们不是尝试确定一周(或一个月)结束的最后一秒,而是获得一周(或一个月)的第一个时刻。 所以一个星期从周一的第一时刻运行,上升,但不包括在下周一的第一刻。

让我们一周的第一天,也是最后一天。 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) 或其他异常情况,一天的第一时刻并不总是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 ) ) ;

毫秒

我强烈建议不要以毫秒为单位进行日期时间工作。 这确实是日期时间类在内部工作的方式,但我们有这些类是有原因的。 处理从纪元开始的计数很笨拙,因为人类无法理解这些值,因此调试和记录很困难且容易出错。 而且,正如我们已经看到的,不同的分辨率可能在起作用; 旧的 Java 类和 Joda-Time 库使用毫秒,而像 Postgres 这样的数据库使用微秒,而现在 java.time 使用纳秒。

您是将文本作为位处理,还是让StringStringBufferStringBuilder处理这些细节?

但是如果你坚持,从ZonedDateTime得到一个Instant ,并从中得到一个毫秒计数从纪元。 但请记住,此调用可能意味着数据丢失 您在ZonedDateTime / Instant可能拥有的任何微秒或纳秒都将被截断(丢失)。

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

关于java.time

java.time框架内置于 Java 8 及更高版本中。 这些类取代麻烦的老传统日期时间类,如java.util.DateCalendar ,和SimpleDateFormat

要了解更多信息,请参阅Oracle 教程 并在 Stack Overflow 上搜索许多示例和解释。 规范是JSR 310

现在处于维护模式Joda-Time项目建议迁移到java.time类。

您可以直接与您的数据库交换java.time对象。 使用符合JDBC 4.2或更高版本的JDBC 驱动程序 不需要字符串,不需要java.sql.*类。

从哪里获得 java.time 类?

注意力!

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包(自 Java8 和后期)获取日/周/月的开始/结束。
下面的 util 类示例:

import org.junit.Test;

import java.time.DayOfWeek;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.TemporalAdjusters;
import java.util.Date;

public class DateUtil {
    private static final ZoneId DEFAULT_ZONE_ID = ZoneId.of("UTC");

    public static LocalDateTime startOfDay() {
        return LocalDateTime.now(DEFAULT_ZONE_ID).with(LocalTime.MIN);
    }

    public static LocalDateTime endOfDay() {
        return LocalDateTime.now(DEFAULT_ZONE_ID).with(LocalTime.MAX);
    }

    public static boolean belongsToCurrentDay(final LocalDateTime localDateTime) {
        return localDateTime.isAfter(startOfDay()) && localDateTime.isBefore(endOfDay());
    }

    //note that week starts with Monday
    public static LocalDateTime startOfWeek() {
        return LocalDateTime.now(DEFAULT_ZONE_ID)
                .with(LocalTime.MIN)
                .with(TemporalAdjusters.previousOrSame(DayOfWeek.MONDAY));
    }

    //note that week ends with Sunday
    public static LocalDateTime endOfWeek() {
        return LocalDateTime.now(DEFAULT_ZONE_ID)
                .with(LocalTime.MAX)
                .with(TemporalAdjusters.nextOrSame(DayOfWeek.SUNDAY));
    }

    public static boolean belongsToCurrentWeek(final LocalDateTime localDateTime) {
        return localDateTime.isAfter(startOfWeek()) && localDateTime.isBefore(endOfWeek());
    }

    public static LocalDateTime startOfMonth() {
        return LocalDateTime.now(DEFAULT_ZONE_ID)
                .with(LocalTime.MIN)
                .with(TemporalAdjusters.firstDayOfMonth());
    }

    public static LocalDateTime endOfMonth() {
        return LocalDateTime.now(DEFAULT_ZONE_ID)
                .with(LocalTime.MAX)
                .with(TemporalAdjusters.lastDayOfMonth());
    }

    public static boolean belongsToCurrentMonth(final LocalDateTime localDateTime) {
        return localDateTime.isAfter(startOfMonth()) && localDateTime.isBefore(endOfMonth());
    }

    public static long toMills(final LocalDateTime localDateTime) {
        return localDateTime.atZone(DEFAULT_ZONE_ID).toInstant().toEpochMilli();
    }

    public static Date toDate(final LocalDateTime localDateTime) {
        return Date.from(localDateTime.atZone(DEFAULT_ZONE_ID).toInstant());
    }

    public static String toString(final LocalDateTime localDateTime) {
        return localDateTime.format(DateTimeFormatter.ISO_DATE_TIME);
    }

    @Test
    public void test() {
        //day
        final LocalDateTime now = LocalDateTime.now();
        System.out.println("Now: " + toString(now) + ", in mills: " + toMills(now));
        System.out.println("Start of day: " + toString(startOfDay()));
        System.out.println("End of day: " + toString(endOfDay()));
        System.out.println("Does '" + toString(now) + "' belong to the current day? > " + belongsToCurrentDay(now));
        final LocalDateTime yesterday = now.minusDays(1);
        System.out.println("Does '" + toString(yesterday) + "' belong to the current day? > " + belongsToCurrentDay(yesterday));
        final LocalDateTime tomorrow = now.plusDays(1);
        System.out.println("Does '" + toString(tomorrow) + "' belong to the current day? > " + belongsToCurrentDay(tomorrow));
        //week
        System.out.println("Start of week: " + toString(startOfWeek()));
        System.out.println("End of week: " + toString(endOfWeek()));
        System.out.println("Does '" + toString(now) + "' belong to the current week? > " + belongsToCurrentWeek(now));
        final LocalDateTime previousWeek = now.minusWeeks(1);
        System.out.println("Does '" + toString(previousWeek) + "' belong to the current week? > " + belongsToCurrentWeek(previousWeek));
        final LocalDateTime nextWeek = now.plusWeeks(1);
        System.out.println("Does '" + toString(nextWeek) + "' belong to the current week? > " + belongsToCurrentWeek(nextWeek));
        //month
        System.out.println("Start of month: " + toString(startOfMonth()));
        System.out.println("End of month: " + toString(endOfMonth()));
        System.out.println("Does '" + toString(now) + "' belong to the current month? > " + belongsToCurrentMonth(now));
        final LocalDateTime previousMonth = now.minusMonths(1);
        System.out.println("Does '" + toString(previousMonth) + "' belong to the current month? > " + belongsToCurrentMonth(previousMonth));
        final LocalDateTime nextMonth = now.plusMonths(1);
        System.out.println("Does '" + toString(nextMonth) + "' belong to the current month? > " + belongsToCurrentMonth(nextMonth));
    }
}

测试输出:

Now: 2020-02-16T22:12:49.957, in mills: 1581891169957
Start of day: 2020-02-16T00:00:00
End of day: 2020-02-16T23:59:59.999999999
Does '2020-02-16T22:12:49.957' belong to the current day? > true
Does '2020-02-15T22:12:49.957' belong to the current day? > false
Does '2020-02-17T22:12:49.957' belong to the current day? > false
Start of week: 2020-02-10T00:00:00
End of week: 2020-02-16T23:59:59.999999999
Does '2020-02-16T22:12:49.957' belong to the current week? > true
Does '2020-02-09T22:12:49.957' belong to the current week? > false
Does '2020-02-23T22:12:49.957' belong to the current week? > false
Start of month: 2020-02-01T00:00:00
End of month: 2020-02-29T23:59:59.999999999
Does '2020-02-16T22:12:49.957' belong to the current month? > true
Does '2020-01-16T22:12:49.957' belong to the current month? > false
Does '2020-03-16T22:12:49.957' belong to the current month? > false

要获取该月的第一天,只需获取一个Date并将当前Date设置为该月的第 1 天。 如果需要,清除小时、分钟、秒和毫秒。

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();
}

我为此创建了一些方法:

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());
}

你可以在这里看到更多。

在这种情况下:

// 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 小时开始

获取下个月的第一个日期:-

SimpleDateFormat df = new SimpleDateFormat("MM-dd-yyyy");
String selectedDate="MM-dd-yyyy like 07-02-2018";
Date dt = df.parse(selectedDate);`enter code here`
calendar = Calendar.getInstance();
calendar.setTime(dt);
calendar.set(Calendar.DAY_OF_MONTH, calendar.getActualMaximum(Calendar.DAY_OF_MONTH) + 1);

String firstDate = df.format(calendar.getTime());
System.out.println("firstDateof next month ==>" + firstDate);
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()));
    }
}

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

 Calendar.getInstance().setTimeInMillis(myDate);

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

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);


    }

}

使用 Java 8 特性的单行解决方案

Java 中

LocalDateTime firstOfWeek = LocalDateTime.now().with(ChronoField.DAY_OF_WEEK, 1).toLocalDate().atStartOfDay(); // 2020-06-08 00:00 MONDAY
LocalDateTime firstOfMonth = LocalDateTime.now().with(ChronoField.DAY_OF_MONTH , 1).toLocalDate().atStartOfDay(); // 2020-06-01 00:00
// Convert to milliseconds: 
firstOfWeek.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli();

科特林

val firstOfWeek = LocalDateTime.now().with(ChronoField.DAY_OF_WEEK, 1).toLocalDate().atStartOfDay() // 2020-06-08 00:00 MONDAY
val firstOfMonth = LocalDateTime.now().with(ChronoField.DAY_OF_MONTH , 1).toLocalDate().atStartOfDay() // 2020-06-01 00:00
// Convert to milliseconds: 
firstOfWeek.atZone(ZoneId.systemDefault()).toInstant().toEpochMilli()

我用这个技巧来获得当月的第一天注意顺序是星期日 1 星期二星期一 3 星期二......等等

Calendar cal = new GregorianCalendar();
int startDay = cal.get(Calendar.DAY_OF_YEAR) % 7 + 1;
System.out.println(startDay);

这是使用Calendar获取所选日期的第一天和最后一天的好方法:

private fun getFirstDayOfWeek(date: Date): Date {
    val calendar = Calendar.getInstance()
    calendar.time = date
    calendar[Calendar.DAY_OF_WEEK] = calendar.firstDayOfWeek
    return calendar.time
}

private fun getLastDayOfWeek(date: Date): Date {
    val calendar = Calendar.getInstance()
    calendar.time = date
    calendar[Calendar.DAY_OF_WEEK] = calendar.firstDayOfWeek
    calendar.add(Calendar.DATE, 6)
    return calendar.time
}

只需要将选定的日期传递给上述函数。

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;     
}

暂无
暂无

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

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