简体   繁体   中英

java - Get the last date of input day of week

I am searching for a method to find the last date of a input day of week from now on? For example: If today is Monday, the 5th march 2018 the results should look like this:

Input      Output
Monday     05.03.2018
Tuesday    27.02.2018
Wednesday  28.02.2018
Thursday   01.03.2018
Friday     02.03.2018
Saturday   03.03.2018
Sunday     04.03.2018

I hope you get the idee. I couldn't really find a post with something similar, so any help would be much appreciated

As posted in comments, this is the code I have atm:

private String getLastDateOfDayOfWeek(String day, String returnDateFormat) throws ParseException {
        int dayOfWeek = parseDayOfWeek(day, Locale.ENGLISH);

        Calendar cal = Calendar.getInstance(); // Today, now
        if (cal.get(Calendar.DAY_OF_WEEK) != dayOfWeek) {
            // ...
        }
        return new SimpleDateFormat(returnDateFormat).format(cal.getTime());
}

private static int parseDayOfWeek(String day, Locale locale)
            throws ParseException {
        SimpleDateFormat dayFormat = new SimpleDateFormat("EEEE", locale);
        Date date = dayFormat.parse(day);
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        int dayOfWeek = calendar.get(Calendar.DAY_OF_WEEK);
        return dayOfWeek;
}

Atm I have two functions: one that can convert a string to a Calender dayOfWeek number and another one, which is the method i am searching for. Currently it only handles todays day of week correct, the part that should do the work for every other day of the week is missing(comment with ...)

tl;dr

LocalDate.now().with(                                // Get today’s date, then move to another date.
    TemporalAdjusters.previousOrSame(                // An implementation of `TemporalAdjuster` interface, used for algorithms to move to another date. 
        DayOfWeek.valueOf( “Monday”.toUpperCase() )  // Get the enum Object with te corresponding hard-coded name in English such as `DayOfWeek.MONDAY`. 
    )
)

DayOfWeek

The DayOfWeek enum holds seven objects, one for each day of the week.

English

The names of these seven objects are in English, all uppercase. So you can get the Object from the English word.

String input = “Monday”.toUpperCase() ;
DayOfWeek dow = DayOfWeek.valueOf( input ) ;

Other languages

For languages other than English, define a List populated with the name of each day-of-week. Use the name generated from DayOfWeek::getDisplayName , a method that automatically localizes. Start the list with Monday, per the ISO 8601 standard. Search that list to find a match with your input. Get the ordinal number of your match, 1-7 (not the index number 0-6). Pass that number to DayOfWeek.valueOf to get a DayOfWeek object. In some languages you'll need a pair of such lists to be searched, as an alternate spelling may be invoked for a “standalone” use of the day-of-week without the context of a date.

Here is an example of such a class. Beware: I just whipped up this class without much thought and without any serious testing. Use at your own risk. Usage: DayOfWeekDelocalizer.of( Locale.CANADA_FRENCH ).parse( "lundi" )DayOfWeek.MONDAY

package com.basilbourque.example;

import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;

import java.time.DayOfWeek;
import java.time.format.TextStyle;
import java.util.ArrayList;
import java.util.List;
import java.util.Locale;

// For a given name of day-of-week in some language, determine the matching `java.time.DayOfWeek` enum object.
// This class is the opposite of `DayOfWeek.getDisplayName` which generates a localized string for a given `DayOfWeek` object.
// Usage… DayOfWeekDelocalizer.of( Locale.CANADA_FRENCH ).parse( "lundi" ) → DayOfWeek.MONDAY
// Assumes `FormatStyle.FULL`, for day-of-week names without abbreviation.
// USE AT YOUR OWN RISK. Rough draft, quickly written. No serious testing.
public class DayOfWeekDelocalizer
{
    @NotNull
    private Locale locale;

    @NotNull
    private List < String > dayOfWeekNames, dayOfWeekNamesStandalone; // Some languages use an alternate spelling for a “standalone” day-of-week used without the context of a date.

    // Constructor. Private, for static factory method.
    private DayOfWeekDelocalizer ( @NotNull Locale locale )
    {
        this.locale = locale;

        // Populate the pair of arrays, each having the translated day-of-week names.
        int daysInWeek = 7; // Seven days in the week.
        this.dayOfWeekNames = new ArrayList <>( daysInWeek );
        this.dayOfWeekNamesStandalone = new ArrayList <>( daysInWeek );

        for ( int i = 1 ; i <= daysInWeek ; i++ )
        {
            this.dayOfWeekNames.add( DayOfWeek.of( i ).getDisplayName( TextStyle.FULL , this.locale ) );
            this.dayOfWeekNamesStandalone.add( DayOfWeek.of( i ).getDisplayName( TextStyle.FULL_STANDALONE , this.locale ) );
        }
//        System.out.println( this.dayOfWeekNames );
//        System.out.println( this.dayOfWeekNamesStandalone );
    }

    // Constructor. Private, for static factory method.
    // Personally, I think it unwise to default implicitly to a `Locale`. But I included this in case you disagree with me, and to follow the lead of the *java.time* classes. --Basil Bourque
    private DayOfWeekDelocalizer ( )
    {
        this( Locale.getDefault() );
    }

    // static factory method, instead of  constructors.
    // See article by Dr. Joshua Bloch. http://www.informit.com/articles/article.aspx?p=1216151
    // The `Locale` argument determines the human language and cultural norms used in de-localizing input strings.
    synchronized static public DayOfWeekDelocalizer of ( @NotNull Locale localeArg )
    {
        DayOfWeekDelocalizer x = new DayOfWeekDelocalizer( localeArg ); // This class could be optimized by caching this object.
        return x;
    }

    // Attempt to translate the name of a day-of-week to look-up a matching `DayOfWeek` enum object. 
    // Returns NULL if the passed String value is not found to be a valid name of day-of-week for the human language and cultural norms of the `Locale` specified when constructing this parent object, `DayOfWeekDelocalizer`.
    @Nullable
    public DayOfWeek parse ( @NotNull String input )
    {
        int index = this.dayOfWeekNames.indexOf( input );
        if ( - 1 == index )
        { // If no hit in the contextual names, try the standalone names.
            index = this.dayOfWeekNamesStandalone.indexOf( input );
        }
        int ordinal = ( index + 1 );
        DayOfWeek dow = ( ordinal > 0 ) ? DayOfWeek.of( ordinal ) : null;  // If we have a hit, determine the DayOfWeek. Else return null.
        return dow;
    }

    // `Object` overrides.

    @Override
    public boolean equals ( Object o )
    {
        if ( this == o ) return true;
        if ( o == null || getClass() != o.getClass() ) return false;

        DayOfWeekDelocalizer that = ( DayOfWeekDelocalizer ) o;

        return locale.equals( that.locale );
    }

    @Override
    public int hashCode ( )
    {
        return locale.hashCode();
    }

    public static void main ( String[] args )
    {
        // Quick testing.
        // DayOfWeekDelocalizer x = DayOfWeekDelocalizer.of( Locale.JAPAN );
        if ( DayOfWeekDelocalizer.of( Locale.CANADA_FRENCH ).parse( "lundi" ).equals( DayOfWeek.MONDAY ) )
        {
            System.out.println( "GOOD - Canada French 'lundi' is parsing to DayOfWeek.MONDAY." );
        } else
        {
            System.out.println( "BAD - Canada French 'lundi' is NOT parsing to DayOfWeek.MONDAY." );
        }
    }
}

Tip: Using a String to represent a DayOfWeek is clumsy. Your code should instead be passing around a DayOfWeek enum object.

LocalDate

Next we need the current date.

LocalDate today = LocalDate.now() ;

Better to explicitly state your desired/expected time zone than rely implicitly on the JVM's current default time zone.

ZoneId z = ZoneId.of( “Africa/Tunis” ) ;
LocalDate today = LocalDate.now( z ) ;

TemporalAdjuster

Move to another date by applying a TemporalAdjuster . The TemporalAdjusters class offers the implementation we need.

TemporalAdjuster ta = TemporalAdjusters.previousOrSame( dow ) ;
LocalDate ld = today.with( ta ) ;

Note that java.time uses Immutable Objects. So rather than modify an object, methods produce a new distinct object with altered values based on the original.


About java.time

The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date , Calendar , & SimpleDateFormat .

The Joda-Time project, now in maintenance mode , advises migration to the java.time classes.

To learn more, see the Oracle Tutorial . And search Stack Overflow for many examples and explanations. Specification is JSR 310 .

You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.

Where to obtain the java.time classes?

The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval , YearWeek , YearQuarter , and more .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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