web-dev-qa-db-fra.com

Java: Obtenir le numéro de semaine de n'importe quelle date?

J'ai un petit programme qui affiche la semaine en cours à partir de la date d'aujourd'hui, comme ceci:

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

Et puis un JLabel qui affiche le numéro de la semaine:

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

Donc maintenant, j'aimerais avoir un JTextField où vous pouvez entrer une date et le JLabel sera mis à jour avec le numéro de semaine de cette date. Je ne suis vraiment pas sûr de savoir comment faire cela car je suis assez nouveau pour Java. Dois-je enregistrer l'entrée en tant que chaîne? Un nombre entier? Et quel format devrait-il être (aaaaMMjj, etc.)? Si quelqu'un pouvait m'aider, je l'apprécierais!

6
Boxiom

Dois-je enregistrer l'entrée en tant que chaîne? Un nombre entier?

Lorsque vous utilisez une JTextField, l'utilisateur que vous obtenez est une String, car la date peut contenir des caractères tels que . ou -, en fonction du format de date choisi. Vous pouvez bien sûr également utiliser des méthodes de saisie plus sophistiquées, dans lesquelles le champ de saisie valide déjà le format de date et renvoie des valeurs distinctes pour le jour, le mois et l'année, mais l'utilisation de JTextField est bien sûr plus facile à utiliser.

Et quel format devrait-il être (aaaaMMjj, etc.)?

Cela dépend de vos besoins. Vous pouvez utiliser la classe SimpleDateFormat pour analyser tout format de date:

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

Mais il est plus probable que vous souhaitiez utiliser le format de date spécifique à votre région:

import Java.text.DateFormat;

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

Pour donner à l'utilisateur un indice sur le format à utiliser, vous devez convertir la variable DateFormat en une variable SimpleDateFormat pour obtenir la chaîne de modèle: 

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

Le commentaire de @adenoyelle ci-dessus me rappelle: Ecrivez des tests unitaires pour votre code d'analyse de date.

19
Andreas Fester

Java 1.8 vous fournit de nouvelles classes dans le 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));

La plupart des calendriers existants peuvent facilement être convertis en Java.time.ZonedDateTime/Java.time.Instant à l'aide de méthodes d'interopérabilité, dans votre cas particulier GregorianCalendar.toZonedDateTime().

9
user667

WeekFields

Cette méthode que j'ai créée fonctionne pour moi dans Java 8 et versions ultérieures en utilisant WeekFields , DateTimeFormatter , LocalDate et TemporalField

N'oubliez pas de formater votre date correctement en fonction de votre cas d'utilisation! 

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;
}
3
Mobolaji D.

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 semaine standard

Si vous voulez la semaine ISO 8601 standard plutôt qu'une définition localisée d'une semaine, utilisez la classe YearWeek trouvée dans le ThreeTen-Extra projet qui ajoute des fonctionnalités aux classes Java.time intégrées à Java 8 et versions ultérieures.

ISO-8601 définit la semaine comme toujours en commençant par lundi. La première semaine est la semaine qui contient le premier jeudi de l'année civile. En tant que tel, l'année de la semaine utilisée dans cette classe ne correspond pas à l'année civile.

D'abord, obtenez la date d'aujourd'hui. La classe LocalDate représente une valeur de date uniquement sans heure et sans fuseau horaire.

Un fuseau horaire est crucial pour déterminer une date. Pour un moment donné, la date varie dans le monde entier par zone. Par exemple, quelques minutes après minuit dans Paris France est un nouveau jour alors qu’il est encore «hier» dans Montréal Québec .

Spécifiez un nom du fuseau horaire } au format continent/region, tel que America/Montreal , Africa/Casablanca ou Pacific/Auckland. N'utilisez jamais les abréviations de 3-4 lettres telles que EST ou IST car elles sont pas de vrais fuseaux horaires, ni normalisés, ni même uniques (!). 

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

Ou laissez l'utilisateur spécifier une date en tapant une chaîne. L'analyse de la saisie d'une date dans une chaîne est couverte dans de nombreux autres questions et réponses. Le plus simple consiste à demander à l'utilisateur d'utiliser le format standard ISO 8601, AAAA-MM-JJ tel que 2017-01-23.

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

Pour les autres formats, spécifiez un DateTimeFormatter pour l'analyse. Rechercher Stack Overflow pour de nombreux exemples d'utilisation de cette classe.

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

Obtenez le YearWeek.

YearWeek yw = YearWeek.from( ld ) ;

Pour créer une chaîne, envisagez d'utiliser le format ISO 8601 standard pour l'année-semaine , aaaa-Www tel que 2017-W45. Ou vous pouvez extraire chaque nombre.

  • YearWeek::getWeek - Obtient le champ Année de la semaine.
  • YearWeek::getYear - Obtient le champ semaine-année.

Autres définitions de semaine

La discussion ci-dessus suppose que vous suivez la définition de semaines ISO 8601 et la numérotation des semaines. Si vous souhaitez plutôt une autre définition de la semaine et de la numérotation hebdomadaire, consultez la Answer by Mobolaji D. en utilisant la définition d’une locale.


À propos de Java.time

Le cadre Java.time est intégré à Java 8 et aux versions ultérieures. Ces classes supplantent les anciennes classes problématiques héritées _ date-heure telles que Java.util.Date , Calendar _, & SimpleDateFormat .

Le projet Joda-Time , désormais en mode { mode de maintenance }, conseille de migrer vers les classes Java.time .

Pour en savoir plus, consultez le Oracle Tutorial . Et recherchez Stack Overflow pour de nombreux exemples et explications. La spécification est JSR 310 .

Vous pouvez échanger des objets Java.time directement avec votre base de données. Utilisez un pilote JDBC compatible avec JDBC 4.2 ou une version ultérieure. Pas besoin de chaînes, pas besoin de Java.sql.* classes.

Où obtenir les classes Java.time? 

Le projet ThreeTen-Extra étend Java.time avec des classes supplémentaires. Ce projet est un terrain d’essai pour d’éventuels ajouts à Java.time. Vous pouvez y trouver des classes utiles telles que Interval _, YearWeek , YearQuarter _ et plus _.

3
Basil Bourque

Vous pouvez stocker la date sous forme de chaîne et l'utilisateur peut la saisir dans n'importe quel format que vous spécifiez. Vous devez simplement utiliser un objet DateFormat pour interpréter la date à laquelle ils ont été entrés. Par exemple, voir le top answer on Convertir une chaîne en objet de calendrier en 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"));

Pour lire la date d'une JTextField, vous pouvez la remplacer par quelque chose comme:

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

Ensuite, il vous suffit de lire le numéro de la semaine à partir de cal de la même manière que dans la question. (Ceci est un exemple simplifié. Vous devez gérer la ParseException potentielle générée par la méthode DateFormatparse .)

3
Bill the Lizard

Vous pouvez l'utiliser, mais vous devez analyser la valeur de date au format de date approprié à l'aide de SimpleDateFormatter of Java API. Vous pouvez spécifier le format de votre choix. Après cela, vous pouvez manipuler pour obtenir la semaine de l'année.

1

celui-ci a fonctionné pour moi

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;
        }
    });
}
0
saigopi
public static int getWeek() {
        return Calendar.getInstance().get(Calendar.WEEK_OF_YEAR);
    }

Fonctionne bien et retourne la semaine pour le temps réel actuel

0
user3408091