简体   繁体   中英

Java: Get week number from any date?

I have a small program that displays the current week from todays date, like this:

GregorianCalendar gc = new GregorianCalendar();
int day = 0;
gc.add(Calendar.DATE, day);

And then a JLabel that displays the week number:

JLabel week = new JLabel("Week " + gc.get(Calendar.WEEK_OF_YEAR));

So right now I'd like to have a JTextField where you can enter a date and the JLabel will update with the week number of that date. I'm really not sure how to do this as I'm quite new to Java. Do I need to save the input as a String? An integer? And what format would it have to be (yyyyMMdd etc)? If anyone could help me out I'd appreciate it!

Do I need to save the input as a String? An integer?

When using a JTextField , the input you get from the user is a String , since the date can contain characters like . or - , depending on the date format you choose. You can of course also use some more sophisticated input methods, where the input field already validates the date format, and returns separate values for day, month and year, but using JTextField is of course easier to start with.

And what format would it have to be (yyyyMMdd etc)?

This depends on your requirements. You can use the SimpleDateFormat class to parse any date format:

String input = "20130507";
String format = "yyyyMMdd";

SimpleDateFormat df = new SimpleDateFormat(format);
Date date = df.parse(input);

Calendar cal = Calendar.getInstance();
cal.setTime(date);
int week = cal.get(Calendar.WEEK_OF_YEAR);

But more likely you want to use the date format specific to your locale:

import java.text.DateFormat;

DateFormat defaultFormat = DateFormat.getDateInstance();
Date date = defaultFormat.parse(input);

To give the user a hint on which format to use, you need to cast the DateFormat to a SimpleDateFormat to get the pattern string:

if (defaultFormat instanceof SimpleDateFormat) {
   SimpleDateFormat sdf = (SimpleDateFormat)defaultFormat;
   System.out.println("Use date format like: " + sdf.toPattern());
}

The comment by @adenoyelle above reminds me: Write unit tests for your date parsing code .

Java 1.8 provides you with some new classes in package java.time :

import java.time.Instant;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.temporal.IsoFields;

ZonedDateTime now = ZonedDateTime.ofInstant(Instant.now(), ZoneId.systemDefault());
System.out.printf("Week %d%n", now.get(IsoFields.WEEK_OF_WEEK_BASED_YEAR));

Most legacy calendars can easily be converted to java.time.ZonedDateTime / java.time.Instant by interoperability methods, in your particular case GregorianCalendar.toZonedDateTime() .

tl;dr

YearWeek.from(                         // Represents week of standard ISO 8601 defined week-based-year (as opposed to a calendar year). 
    LocalDate.parse( "2017-01-23" )    // Represents a date-only value, without time-of-day and without time zone.
)                                      // Returns a `YearWeek` object.
.getWeek()                             // Or, `.getYear()`. Both methods an integer number.

4

ISO 8601 standard week

If you want the standard ISO 8601 week , rather than a localized definition of a week, use the YearWeek class found in the ThreeTen-Extra project that adds functionality to the java.time classes built into Java 8 and later.

ISO-8601 defines the week as always starting with Monday. The first week is the week which contains the first Thursday of the calendar year. As such, the week-based-year used in this class does not align with the calendar year.

First, get today's date. The LocalDate class represents a date-only value without time-of-day and without time zone.

A time zone is crucial in determining a date. For any given moment, the date varies around the globe by zone. For example, a few minutes after midnight in Paris France is a new day while still “yesterday” in Montréal Québec .

Specify a proper time zone name in the format of continent/region , such as America/Montreal , Africa/Casablanca , or Pacific/Auckland . Never use the 3-4 letter abbreviation such as EST or IST as they are not true time zones, not standardized, and not even unique(!).

ZoneId z = ZoneId.of( "America/Montreal" );
LocalDate today = LocalDate.now( z );

Or let the user specify a date by typing a string. Parsing string input of a date is covered in many other Questions and Answers. Simplest is to have the user use standard ISO 8601 format, YYYY-MM-DD such as 2017-01-23 .

LocalDate ld = LocalDate.parse( "2017-01-23" ) ; 

For other formats, specify a DateTimeFormatter for parsing. Search Stack Overflow for many many examples of using that class.

DateTimeFormatter f = DateTimeFormatter.ofPattern( "d/M/uuuu" , Locale.US ) ;
LocalDate ld = LocalDate.parse( "1/23/2017" , f ) ;

Get the YearWeek .

YearWeek yw = YearWeek.from( ld ) ;

To create a string, consider using the standard ISO 8601 format for year-week , yyyy-Www such as 2017-W45 . Or you can extract each number.

  • YearWeek::getWeek – Gets the week-of-week-based-year field.
  • YearWeek::getYear – Gets the week-based-year field.

Other definitions of week

The above discussion assumes you go by the ISO 8601 definition of weeks and week-numbering. If instead you want an alternate definition of week and week-numbering, see the Answer by Mobolaji D. using a locale's definition.


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 .

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

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

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. Hibernate 5 & JPA 2.2 support java.time .

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 .

WeekFields

This method that I created works for me in Java 8 and later, using WeekFields , DateTimeFormatter , LocalDate , and TemporalField .

Don't forget to format your date properly based on your use case!

public int getWeekNum(String input) {
    DateTimeFormatter formatter = DateTimeFormatter.ofPattern("M/dd/yy");   // Define formatting pattern to match your input string.
    LocalDate date = LocalDate.parse(input, formatter);                     // Parse string into a `LocalDate` object.

    WeekFields wf = WeekFields.of(Locale.getDefault()) ;                    // Use week fields appropriate to your locale. People in different places define a week and week-number differently, such as starting on a Monday or a Sunday, and so on.
    TemporalField weekNum = wf.weekOfWeekBasedYear();                       // Represent the idea of this locale’s definition of week number as a `TemporalField`. 
    int week = Integer.parseInt(String.format("%02d",date.get(weekNum)));   // Using that locale’s definition of week number, determine the week-number for this particular `LocalDate` value.

    return week;
}

You can store the date as a String, and the user can enter it in pretty much any format you specify. You just need to use a DateFormat object to interpret the date that they enter. For example, see the top answer on Convert String to Calendar Object in Java .

Calendar cal = Calendar.getInstance();
SimpleDateFormat sdf = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy");
cal.setTime(sdf.parse("Mon Mar 14 16:02:37 GMT 2011"));

To read the date from a JTextField , you could replace that with something like:

SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd"); // or any other date format
cal.setTime(sdf.parse(dateTextField.getText()));

Then you just need to read the week number from cal in the same way you showed in the question. (This is a simplified example. You'd need to handle the potential ParseException thrown by the DateFormat parse method.)

You can use that, but you have to parse the date value to proper date format using SimpleDateFormatter of java API . You can specify any format you want. After that you can do you manipulation to get the week of the year.

public static int getWeek() {
        return Calendar.getInstance().get(Calendar.WEEK_OF_YEAR);
    }

Works fine and return week for current realtime

this one worked for me

public void sortListItems(List<PostModel> list) {
    Collections.sort(list, new Comparator<PostModel>() {
        DateFormat dateFormat = new SimpleDateFormat("dd/MM/yyyy HH:mm:ss");
        @Override
        public int compare(PostModel o1, PostModel o2) {
            int ret = 0;
            try {
                ret = dateFormat.parse(o1.getDate()).compareTo(dateFormat.parse(o2.getDate()));
                return ret;
            } catch (ParseException e) {
                e.printStackTrace();
            }

            return ret;
        }
    });
}

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