JavaRush /Blog Java /Random-FR /Comment ne pas se perdre dans le temps - DateTime et Cale...

Comment ne pas se perdre dans le temps - DateTime et Calendar

Publié dans le groupe Random-FR
Bonjour! Aujourd'hui, nous allons commencer à travailler avec un nouveau type de données que nous n'avons jamais rencontré auparavant, à savoir les dates. Comment ne pas se perdre dans le temps - DateTime et Calendar - 1Je pense qu'il n'est pas nécessaire d'expliquer ce qu'est une date :) En principe, il est tout à fait possible d'écrire la date et l'heure actuelles en Java dans une chaîne normale.
public class Main {
   public static void main(String[] args) {

       String date = "June 11, 2018";
       System.out.println(date);
   }
}
Mais cette approche présente de nombreux inconvénients. La classe Stringa été créée pour travailler avec du texte et dispose de méthodes appropriées. Si nous devons gérer la date d’une manière ou d’une autre (y ajouter 2 heures par exemple), cela Stringne fonctionnera pas ici. Ou, par exemple, affichez la date et l'heure actuelles au moment où le programme a été compilé dans la console. Cela n'aidera pas non plus ici String: pendant que vous écrivez le code et l'exécutez, l'heure changera et ce qui n'est pas pertinent sera affiché dans la console. Par conséquent, en Java, ses créateurs ont proposé plusieurs classes pour travailler avec les dates et les heures. Le premier est la classejava.util.Date

Classe de dates Java

Nous lui avons donné son nom complet car il existe également une classe dans un autre package en Java java.sql.Date. Ne vous y trompez pas ! La première chose que vous devez savoir est qu’il stocke la date en millisecondes écoulées depuis le 1er janvier 1970. Il existe même un nom distinct pour cette date - "Heure Unix". Une manière assez intéressante, n'est-ce pas ? :) La deuxième chose à retenir : si vous créez un objet Dateavec un constructeur vide, le résultat sera la date et l'heure actuelles au moment de la création de l'objet . StringVous souvenez-vous de la façon dont nous avions écrit qu'une telle tâche serait problématique pour un format de date ? La classe Datele résout facilement.
public class Main {
   public static void main(String[] args) {

       Date date = new Date();
       System.out.println(date);
   }
}
Exécutez ce code plusieurs fois et vous verrez comment l'heure changera à chaque fois :) Ceci est possible précisément parce qu'il est stocké en millisecondes : c'est la plus petite unité de temps, c'est pourquoi les résultats sont si précis. Il existe un autre constructeur pour Date: vous pouvez spécifier le nombre exact de millisecondes qui se sont écoulées entre 00h00 le 1er janvier 1970 et la date souhaitée, et il sera créé :
public class Main {
   public static void main(String[] args) {

       Date date = new Date(1212121212121L);
       System.out.println(date);
   }
}
Sortie de la console :

Fri May 30 08:20:12 MSD 2008
Nous l'avons reçu le 30 mai 2008. « Fri » signifie le jour de la semaine - « vendredi » (vendredi) et MSD - « heure d'été de Moscou » (heure d'été de Moscou). Les millisecondes sont transmises au format long, car leur nombre ne rentre le plus souvent pas dans int. Alors, de quel type d’opérations de date pourrions-nous avoir besoin dans notre travail ? Eh bien, la chose la plus évidente, bien sûr, est la comparaison . Déterminez si une date était postérieure ou antérieure à une autre. Cela peut se faire de différentes façons. Par exemple, vous pouvez appeler la méthode . Date.getTime(), qui renverra le nombre de millisecondes écoulées depuis le 1er janvier 1970 à minuit. Appelons-le simplement sur deux objets Date et comparons-les entre eux :
public class Main {
   public static void main(String[] args) {

       Date date1 = new Date();

       Date date2 = new Date();

       System.out.println((date1.getTime() > date2.getTime())?
               "date1 is later than date2" : "date1 is earlier than date2");
   }
}
Conclusion:

date1 раньше date2
Mais il existe un moyen plus pratique, à savoir utiliser des méthodes spéciales de la classe Date: before(), after()et equals(). Ils renvoient tous le résultat dans boolean. La méthode before()vérifie si notre date est antérieure à celle que nous passons en argument :
public class Main {
   public static void main(String[] args) throws InterruptedException {

       Date date1 = new Date();

       Thread.sleep(2000);//pause the program for 2 seconds
       Date date2 = new Date();

       System.out.println(date1.before(date2));
   }
}
Sortie de la console :

true
La méthode fonctionne de manière similaire after(); elle vérifie si notre date est postérieure à celle que nous passons en argument :
public class Main {
   public static void main(String[] args) throws InterruptedException {

       Date date1 = new Date();

       Thread.sleep(2000);//pause the program for 2 seconds
       Date date2 = new Date();

       System.out.println(date1.after(date2));
   }
}
Sortie de la console :

false
Dans nos exemples, nous mettons le programme en veille pendant 2 secondes afin que les deux dates soient garanties différentes. Sur les ordinateurs rapides, le temps entre la création date1de et date2peut être inférieur à une milliseconde, auquel cas and before()et after()renverront false. Mais la méthode equals()dans une telle situation reviendra true! Après tout, il compare exactement le nombre de millisecondes écoulées depuis le 1er janvier 1970 à minuit pour chaque date. Les objets ne seront considérés comme égaux que s’ils correspondent à la milliseconde près :
public static void main(String[] args) {

   Date date1 = new Date();
   Date date2 = new Date();

   System.out.println(date1.getTime());
   System.out.println(date2.getTime());

   System.out.println(date1.equals(date2));
}
Voici autre chose auquel vous devez prêter attention. Si vous ouvrez la documentation de la classe Datesur le site Web d'Oracle, vous verrez que bon nombre de ses méthodes et constructeurs ont été désignés comme Deprecated(« obsolètes »). Ici, regardez : Class Date Voici ce que les créateurs de Java eux-mêmes disent à propos des parties des classes devenues obsolètes : "Un élément de programme annoté avec @Deprecated est quelque chose qu'il est déconseillé aux programmeurs d'utiliser, généralement parce qu'il est dangereux, ou parce que cela il existe une meilleure alternative. Cela ne veut pas dire que ces méthodes ne peuvent pas du tout être utilisées. De plus, si vous essayez vous-même d'exécuter le code en les utilisant dans IDEA, cela fonctionnera très probablement. Prenons par exemple la méthode obsolète Date.getHours(), qui renvoie le nombre d'heures de l'objet Date.
public static void main(String[] args) {

   Date date1 = new Date();

   System.out.println(date1.getHours());

}
Si au moment où vous exécutez le code, par exemple, il est 14h21, il affichera le chiffre 14. Comme vous pouvez le constater, la méthode obsolète est barrée, mais elle fonctionne plutôt bien. Ces méthodes n'ont pas été complètement supprimées, afin de ne pas casser un tas de code déjà écrit avec elles. Autrement dit, ces méthodes ne sont ni « cassées » ni « supprimées », leur utilisation n'est tout simplement pas recommandée en raison de la disponibilité d'une alternative plus pratique. D'ailleurs, cela est écrit directement dans la documentation : Comment ne pas se perdre dans le temps - DateTime et Calendar - 2la plupart des méthodes de la classe Date ont été déplacées vers sa version améliorée et étendue - la classe Calendar. Nous apprendrons à le connaître davantage :)

Calendrier Java

Java 1.1 a introduit une nouvelle classe - Calendar. Il a rendu le travail avec les dates en Java un peu plus facile qu'auparavant. La seule implémentation de la classe Calendaravec laquelle nous travaillerons est la classe GregorianCalendar(elle implémente le calendrier grégorien, selon lequel vivent la plupart des pays du monde). Son principal avantage est qu'il peut travailler avec des dates dans un format plus pratique. Il peut par exemple :
  • Ajouter un mois ou un jour à la date actuelle
  • Vérifiez si l'année est une année bissextile ;
  • Obtenez des composants de date individuels (par exemple, obtenez le numéro du mois à partir d'une date entière)
  • Et aussi, un système de constantes très pratique a été développé à l'intérieur (nous en verrons beaucoup ci-dessous).
Une autre différence importante de la classe Calendarest qu'elle implémente une constante Calendar.Era: vous pouvez régler la date sur l'ère BC (« Avant Christ » - avant la naissance du Christ, c'est-à-dire « avant notre ère ») ou AC (« Après Christ » - « notre époque"). Regardons tout cela avec des exemples. Créons un calendrier avec la date du 25 janvier 2017 :
public static void main(String[] args) {

  Calendar calendar = new GregorianCalendar(2017, 0 , 25);
}
Les mois dans la classe Calendar(comme dans Date, d'ailleurs) commencent à zéro, nous avons donc passé le chiffre 0 comme deuxième argument. L'essentiel lorsque l'on travaille avec une classe Calendarest de comprendre qu'il s'agit d'un calendrier et non d'une date distincte. Comment ne pas se perdre dans le temps - DateTime et Calendar - 3Une date est simplement une série de chiffres représentant une période de temps spécifique. Et un calendrier est un appareil à part entière avec lequel vous pouvez faire beaucoup de choses avec des dates :) Cela peut être vu assez clairement si vous essayez d'afficher l'objet Calendrier sur la console : Sortie :

java.util.GregorianCalendar[time=?,areFieldsSet=false,areAllFieldsSet=false,lenient=true,zone=sun.util.calendar.ZoneInfo[id="Europe/Moscow",offset=10800000,dstSavings=0,useDaylight=false,transitions=79,lastRule=null],firstDayOfWeek=2,minimalDaysInFirstWeek=1,ERA=?,YEAR=2017,MONTH=0,WEEK_OF_YEAR=?,WEEK_OF_MONTH=?,DAY_OF_MONTH=25,DAY_OF_YEAR=?,DAY_OF_WEEK=?,DAY_OF_WEEK_IN_MONTH=?,AM_PM=0,HOUR=0,HOUR_OF_DAY=0,MINUTE=0,SECOND=0,MILLISECOND=?,ZONE_OFFSET=?,DST_OFFSET=?]
Voyez combien d’informations il y a ! Le calendrier a un tas de propriétés qu'une date normale n'a pas, et toutes sont affichées sur la console (c'est ainsi que fonctionne la méthode toString()de la classe Calendar). Si, lorsque vous travaillez, vous avez simplement besoin d'obtenir une simple date du calendrier, c'est-à-dire objet Date- cela se fait à l'aide d'une méthode Calendar.getTime()(le nom n'est pas le plus logique, mais rien ne peut être fait) :
public static void main(String[] args) {

   Calendar calendar = new GregorianCalendar(2017, 0 , 25);
   Date date = calendar.getTime();
   System.out.println(date);
}
Conclusion:

Wed Jan 25 00:00:00 MSK 2017
Nous avons désormais « simplifié » le calendrier à une date régulière. Allons-nous en. En plus des symboles numériques des mois, Calendarles constantes peuvent être utilisées en classe. Les constantes sont des champs statiques d'une classe Calendaravec une valeur déjà définie qui ne peut pas être modifiée. Cette option est en réalité meilleure, car elle améliore la lisibilité du code.
public static void main(String[] args) {
   GregorianCalendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
}
Calendar.JANUARY— une des constantes pour indiquer le mois. Avec cette option de dénomination, personne n'oubliera, par exemple, que le chiffre « 3 » signifie avril, et non le troisième mois auquel nous sommes habitués - mars. Il vous suffit d'écrire Calendar.APRIL- et c'est tout :) Tous les champs du calendrier (jour, mois, minutes, secondes, etc.) peuvent être définis individuellement à l'aide de la méthode set(). C'est très pratique, car Calendarchaque champ a sa propre constante dans la classe et le code final semblera aussi simple que possible. Par exemple, dans l’exemple précédent, nous avons créé une date, mais n’avons pas défini l’heure actuelle. Régleons l'heure à 19:42:12
public static void main(String[] args) {
   Calendar calendar = new GregorianCalendar();
   calendar.set(Calendar.YEAR, 2017);
   calendar.set(Calendar.MONTH, 0);
   calendar.set(Calendar.DAY_OF_MONTH, 25);
   calendar.set(Calendar.HOUR_OF_DAY, 19);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   System.out.println(calendar.getTime());
}
Conclusion:

Wed Jan 25 19:42:12 MSK 2017
On appelle la méthode set(), on lui passe une constante (selon le champ que l'on souhaite modifier) ​​et une nouvelle valeur pour ce champ. Il s'avère que la méthode set()est une sorte de "super-setter" qui peut définir une valeur non pas pour un champ, mais pour plusieurs champs :) L'ajout et la soustraction de valeurs dans une classe Calendars'effectuent à l'aide du add(). Vous devez y transmettre le champ que vous souhaitez modifier et le nombre - exactement combien vous souhaitez ajouter/soustraire de la valeur actuelle. Par exemple, remontons la date de création à 2 mois :
public static void main(String[] args) {
   Calendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
   calendar.set(Calendar.HOUR, 19);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   calendar.add(Calendar.MONTH, -2);//to subtract a value - a negative number must be passed to the method
   System.out.println(calendar.getTime());
}
Conclusion:

Fri Nov 25 19:42:12 MSK 2016
Super! Nous avons ramené la date à 2 mois. En conséquence, non seulement le mois, mais aussi l'année ont changé, de 2017 à 2016. Le calcul de l'année en cours lors du déplacement des dates, bien entendu, est effectué automatiquement et n'a pas besoin d'être contrôlé manuellement. Mais si, pour une raison quelconque, vous devez désactiver ce comportement, vous pouvez le faire. Une méthode spéciale roll()peut ajouter et soustraire des valeurs sans affecter les autres valeurs. Par exemple, comme ceci :
public static void main(String[] args) {
   Calendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
   calendar.set(Calendar.HOUR, 10);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   calendar.roll(Calendar.MONTH, -2);
   System.out.println(calendar.getTime());
}
Nous avons fait exactement la même chose que dans l'exemple précédent : nous avons soustrait 2 mois à la date actuelle. Mais maintenant, le code fonctionnait différemment : le mois changeait de janvier à novembre, mais l'année restait la même que 2017 ! Conclusion:

Sat Nov 25 10:42:12 MSK 2017
Plus loin. Comme nous l'avons dit plus haut, tous les champs d'un objet Calendarpeuvent être obtenus séparément. La méthode est responsable de cela get():
public static void main(String[] args) {
   GregorianCalendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
   calendar.set(Calendar.HOUR, 10);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   System.out.println("Year: " + calendar.get(Calendar.YEAR));
   System.out.println("Month: " + calendar.get(Calendar.MONTH));
   System.out.println("Number of the week in the month: " + calendar.get(Calendar.WEEK_OF_MONTH));// serial number of the week in the month

   System.out.println("Number: " + calendar.get(Calendar.DAY_OF_MONTH));

   System.out.println("Watch: " + calendar.get(Calendar.HOUR));
   System.out.println("Minutes: " + calendar.get(Calendar.MINUTE));
   System.out.println("Seconds: " + calendar.get(Calendar.SECOND));
   System.out.println("Milliseconds: " + calendar.get(Calendar.MILLISECOND));

}
Conclusion:

Год: 2017 
Месяц: 0 
Порядковый номер недели в месяце: 4 
Число: 25 
Часы: 10 
Минуты: 42 
Секунды: 12 
Миллисекунды: 0
Autrement dit, en plus du « super-setter » dans la classe, Calendaril y a aussi un « super-getter » :) Un autre point intéressant est, bien sûr, le travail avec les époques. Pour créer une date « BC », vous devez utiliser le champ. Calendar.Era Par exemple, créons une date indiquant la bataille de Cannes, au cours de laquelle Hannibal a vaincu l'armée de Rome. Cela s'est produit le 2 août 216 avant JC. e.:
public static void main(String[] args) {
   GregorianCalendar cannes = new GregorianCalendar(216, Calendar.AUGUST, 2);
   cannes.set(Calendar.ERA, GregorianCalendar.BC);

   DateFormat df = new SimpleDateFormat("dd MMM yyy GG");
   System.out.println(df.format(cannes.getTime()));
}
Ici nous avons utilisé la classe SimpleDateFormatpour afficher la date dans un format qui nous est plus compréhensible (les lettres « GG » se chargent d'afficher l'époque). Conclusion:

02 авг 216 до н.э.
CalendarIl existe de nombreuses autres méthodes et constantes dans la classe , lisez-les dans la documentation :

Conversion d'une chaîne en date

Pour convertir une chaîne en date, vous pouvez utiliser la classe d'assistance Java - SimpleDateFormat . C'est la classe dont vous avez besoin pour convertir une date dans un format que vous définissez. Comment ne pas se perdre dans le temps - DateTime et Calendar - 5À son tour, il est très similaire à DateFormat . La seule différence notable entre les deux est que SimpleDateFormat peut être utilisé pour le formatage (conversion d'une date en chaîne) et l'analyse de la chaîne en une date tenant compte des paramètres régionaux, alors que DateFormat ne prend pas en charge les paramètres régionaux. De plus, DateFormat est une classe abstraite qui fournit une prise en charge de base pour le formatage et l'analyse des dates, tandis que SimpleDateFormat est une classe concrète qui étend la classe DateFormat. Voici à quoi ressemble un exemple de création d'un objet SimpleDateFormat et de formatage d'une Date :
SimpleDateFormat formater = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
Date date = new Date(1212121212121L);

System.out.println(formatter.format(date));
Dans l'exemple ci-dessus, nous avons utilisé le modèle « aaaa-MM-jj HH:mm:ss » qui signifie :
  • 4 chiffres pour l'année (aaaa);
  • 2 chiffres pour le mois (MM) ;
  • 2 chiffres pour le jour (jj) ;
  • 2 chiffres pour les heures au format 24 heures (HH) ;
  • 2 chiffres pour les minutes (mm) ;
  • 2 chiffres pour les secondes (ss).
Les marques de séparation et l'ordre des symboles du motif sont conservés. Sortie de la console :
2008-05-30 08:20:12
Il existe de nombreux modèles de lettres pour la classe SimpleDateFormat . Pour que vous ne vous trompiez pas, nous les avons rassemblés dans un tableau :
Symbole Description Exemple
g era (en localisation anglaise - AD et BC) ANNONCE
oui année (numéro à 4 chiffres) 2020
aa année (2 derniers chiffres) 20
aaaa année (numéro à 4 chiffres) 2020
M numéro du mois (sans les zéros non significatifs) 8
MM numéro du mois (avec des zéros non significatifs si numéro du mois < 10) 04
MMM abréviation du mois à trois lettres (selon la localisation) Jan
MMMMM nom complet du mois Juin
w semaine de l'année (sans zéros non significatifs) 4
ww semaine de l'année (avec des zéros non significatifs) 04
W semaine dans le mois (sans zéros non significatifs) 3
WW semaine dans le mois (avec zéro en tête) 03
D jour de l'année 67
d jour du mois (sans les zéros non significatifs) 9
jj jour du mois (avec des zéros non significatifs) 09
F jour de la semaine dans le mois (sans zéros non significatifs) 9
FR jour de la semaine dans le mois (avec des zéros non significatifs) 09
E jour de la semaine (abréviation) W
EEEE jour de la semaine (complet) Vendredi
toi numéro du jour de la semaine (sans les zéros non significatifs) 5
euh numéro du jour de la semaine (avec des zéros non significatifs) 05
un Marqueur AM/PM SUIS.
H heures au format 24 heures sans zéros non significatifs 6
HH horloge au format 24 heures avec zéro non significatif 06
k nombre d'heures au format 24 heures 18
K nombre d'heures au format 12 heures 6
h heure au format 12 heures sans zéros non significatifs 6
hh heure au format 12 heures avec un zéro non significatif 06
m minutes sans zéros non significatifs 32
mm minutes avec un zéro non significatif 32
s secondes sans zéros non significatifs onze
ss secondes avec un zéro non significatif onze
S millisecondes 297
z Fuseau horaire eet
Z fuseau horaire au format RFC 822 300
Exemples de combinaisons de caractères de motif :
Échantillon Exemple
jj-MM-aaaa 01-11-2020
aaaa-MM-jj 2019-10-01
HH:mm:ss.SSS 23:59.59.999
aaaa-MM-jj HH:mm:ss 2018-11-30 03:09:02
aaaa-MM-jj HH:mm:ss.SSS 2016-03-01 01:20:47.999
aaaa-MM-jj HH:mm:ss.SSS Z 2013-13-13 23:59:59.999 +0100
Si vous faites une légère erreur avec le format, vous pouvez devenir propriétaire d'une java.text.ParseException, et ce n'est pas une réalisation particulièrement agréable. Eh bien, la courte excursion dans SimpleDateFormat est terminée - revenons à la traduction de la chaîne Java à ce jour . SimpleDateFormat nous offre de telles capacités, et nous suivrons ce processus étape par étape.
  1. Créez une ligne à partir de laquelle vous devez définir la date :

    String strDate = "Sat, April 4, 2020";
  2. Nous créons un nouvel objet SimpleDateFormat avec un modèle qui correspond à ce que nous avons dans la chaîne (sinon nous ne pourrons pas l'analyser) :

    SimpleDateFormat formatter = new SimpleDateFormat("EEE, MMMM d, yyyy", Locale.ENGLISH);

    Comme vous pouvez le voir, nous avons ici un argument Locale. Si nous l'omettons, il utilisera la langue par défaut, qui n'est pas toujours l'anglais.

    Si les paramètres régionaux ne correspondent pas à la chaîne d'entrée, alors les données de chaîne liées à la langue, comme la nôtre Mon ou April , ne seront pas reconnues et lanceront une java.text.ParseException, même si le modèle correspond.

    Cependant, nous n'avons pas besoin de spécifier le format si nous utilisons un modèle qui n'est pas spécifique à une langue. À titre d'exemple - aaaa-MM-jj HH:mm:ss

  3. Nous créons une date à l'aide d'un formateur, qui à son tour l'analyse à partir de la chaîne d'entrée :

    try {
      Date date = formatter.parse(strDate);
      System.out.println(date);
    }
    catch (ParseException e) {
      e.printStackTrace();
    }

    Sortie de la console :

    
    Sat Apr 04 00:00:00 EEST 2020

    Hmmm... Mais le format n'est plus le même !

    Pour faire le même format, on utilise à nouveau le formateur :

    System.out.println(formatter.format(date));

    Sortie de la console :

    
    Sat, April 4, 2020

SimpleDateFormat et calendrier

SimpleDateFormat vous permet de formater tous les objets Date et Calendrier que vous créez pour une utilisation ultérieure. Considérons un point aussi intéressant que le travail avec les époques. Pour créer une date « BC », vous devez utiliser le champ Calendar.Era. Par exemple, créons une date indiquant la bataille de Cannes, au cours de laquelle Hannibal a vaincu l'armée de Rome. Cela s'est produit le 2 août 216 avant JC. e.:
public static void main(String[] args) {
   GregorianCalendar cannes = new GregorianCalendar(216, Calendar.AUGUST, 2);
   cannes.set(Calendar.ERA, GregorianCalendar.BC);

   DateFormat df = new SimpleDateFormat("dd MMM yyy GG");
   System.out.println(df.format(cannes.getTime()));
}
Ici nous avons utilisé la classe SimpleDateFormat pour afficher la date dans un format qui nous est plus compréhensible (comme indiqué ci-dessus, les lettres « GG » se chargent d'afficher l'époque). Conclusion:

02 авг 216 до н.э.

Format de date Java

Voici un autre cas. Supposons que ce format de date ne nous convienne pas :

Sat Nov 25 10:42:12 MSK 2017
Alors voilà. Grâce à nos capacités de format de date Java, vous pouvez le modifier sans trop de difficulté :
public static void main(String[] args) {

   SimpleDateFormat dateFormat = new SimpleDateFormat("EEEE, d MMMM yyyy");
   Calendar calendar = new GregorianCalendar(2017, Calendar.JANUARY , 25);
   calendar.set(Calendar.HOUR, 10);
   calendar.set(Calendar.MINUTE, 42);
   calendar.set(Calendar.SECOND, 12);

   calendar.roll(Calendar.MONTH, -2);
   System.out.println(dateFormat.format(calendar.getTime()));
}
Conclusion:

суббота, 25 Ноябрь 2017
Beaucoup mieux, non ? :)
Commentaires
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION