Joda hora mais dias com data errada

Sep 07 2020

Estou usando este código:

 DateTime(date)//Thu Aug 06 00:00:00 GMT+03:00 2020
                .plusDays(days) // 103
                .toDate()

E o resultado é em Fri Dec 18 23:00:00 GMT+02:00 2020vez de Dec 19. Com algumas datas funciona bem, com outras o resultado data-1, acho que o problema é com o número de dias do mês, mas plusDays()não considera?

Respostas

2 LiveandLetLive Sep 07 2020 at 09:32

Com algumas datas funciona bem, com outras o resultado date-1, acho que o problema é com o número de dias no mês, mas plusDays () não considera isso?

Ele considera isso. O problema com as duas strings de data e hora que você mencionou é que elas pertencem a diferentes zonas de deslocamento (a primeira é com UTC + 3 e a segunda com UTC + 2). Dada a seguir é como fazer isso com o mesmo Zone-Offset.

import org.joda.time.DateTime;
import org.joda.time.DateTimeZone;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        DateTimeFormatter formatter = DateTimeFormat.forPattern("EEE MMM dd HH:mm:ss zZ yyyy");
        DateTime dateTime = DateTime.parse("Thu Aug 06 00:00:00 GMT+03:00 2020", formatter);
        System.out.println(dateTime);
        // With Zone-Offset of UTC+2
        System.out.println(dateTime.withZone(DateTimeZone.forOffsetHours(2)));

        // Add 103 days
        DateTime dateTimeAfter103Days = dateTime.plusDays(103);
        System.out.println(dateTimeAfter103Days);
        System.out.println(dateTime.withZone(DateTimeZone.forOffsetHours(2)));
    }
}

Resultado:

2020-08-05T21:00:00.000Z
2020-08-05T23:00:00.000+02:00
2020-11-16T21:00:00.000Z
2020-08-05T23:00:00.000+02:00

Eu recomendo que você use a API de data e hora moderna java.time e a API de formatação correspondente (pacote, java.time.format). Saiba mais sobre a API de data e hora moderna em Trail: Date Time . Se o seu nível de API do Android ainda não for compatível com Java8, verifique Como usar o ThreeTenABP no Android Project e as APIs do Java 8+ disponíveis por meio de desugaring .

A tabela a seguir mostra uma visão geral das classes modernas de data e hora :

Com API de data e hora moderna:

import java.time.OffsetDateTime;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        // Define formatter for your date-time string
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss O u");

        // Parse the given date0-time string into OffsetDateTime object
        OffsetDateTime dateTime = OffsetDateTime.parse("Thu Aug 06 00:00:00 GMT+03:00 2020", formatter);
        System.out.println(dateTime);

        // Add 103 days to the OffsetDateTime object
        OffsetDateTime dateTimeAfter103Days = dateTime.plusDays(103);
        System.out.println(dateTimeAfter103Days);
    }
}

Resultado:

2020-08-06T00:00+03:00
2020-11-17T00:00+03:00

Alternativamente,

import java.time.LocalDateTime;
import java.time.OffsetDateTime;
import java.time.ZoneOffset;
import java.time.format.DateTimeFormatter;

public class Main {
    public static void main(String[] args) {
        // Define formatter for your date-time string
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss z yyyy");

        // If you do not need Zone Id or Zone Offset information, you can go for
        // LocalDateTime
        LocalDateTime dateTime = LocalDateTime.parse("Thu Aug 06 00:00:00 GMT+03:00 2020", formatter);
        System.out.println(dateTime);

        // You can convert LocalDateTime object into an OffsetDateTime by applying the
        // Zone-Offset e.g. the following line applies UTC+03:00 hours to LocalDateTime
        OffsetDateTime odt = dateTime.atOffset(ZoneOffset.ofHours(3));
        System.out.println(odt);

        // Add 103 days to the LocalDateTime object
        LocalDateTime dateTimeAfter103Days = dateTime.plusDays(103);
        System.out.println(dateTimeAfter103Days);

        odt = dateTimeAfter103Days.atOffset(ZoneOffset.ofHours(3));
        System.out.println(odt);
    }
}

Resultado:

2020-08-06T00:00
2020-08-06T00:00+03:00
2020-11-17T00:00
2020-11-17T00:00+03:00
3 deHaar Sep 07 2020 at 09:33

Você pode usar java.timee é compatível com APIs Android inferiores, porque agora há desugar de APIs no Android .

Há uma classe com reconhecimento de zona ( java.time.ZonedDateTime) e outra com reconhecimento de deslocamento ( java.time.OffsetDateTime), mas seu exemplo Stringcontém apenas um deslocamento do GMT / UTC. É por isso que eu usaria um OffsetDateTimeque analisa o momento exato no tempo e adiciona um dia.

Aqui está um exemplo simples que define um formatador que analisa o dado Stringe o usa para a saída:

public static void main(String[] args) {
    // example String
    String date = "Fri Dec 18 23:00:00 GMT+02:00 2020";
    // create a formatter that is able to parse and output the String
    DateTimeFormatter dtf = DateTimeFormatter.ofPattern("EEE MMM dd HH:mm:ss OOOO uuuu",
                                                        Locale.ENGLISH);
    // parse the String using the formatter defined above
    OffsetDateTime odt = OffsetDateTime.parse(date, dtf);
    System.out.println("OffsetDateTime parsed is\t" + odt.format(dtf));
    
    // add a day to the date part
    OffsetDateTime dayLater = odt.plusDays(1);
    System.out.println("Adding a day results in\t\t" + dayLater.format(dtf));
}

Isso produz

OffsetDateTime parsed is    Fri Dec 18 23:00:00 GMT+02:00 2020
Adding a day results in     Sat Dec 19 23:00:00 GMT+02:00 2020

Se você estiver interessado em produzir apenas datas (sem parte do tempo ou deslocamento), há outra coisa útil nessas classes, que é a extração fácil da parte da data ou hora. Você pode fazer o seguinte com um OffsetDateTime, por exemplo:

// extract the part that only holds information about day of month, month of year and year
LocalDate dateOnly = odt.toLocalDate();
// print the default format (ISO standard)
System.out.println(dateOnly);
// or define and use a totally custom format
System.out.println(dateOnly.format(
                        DateTimeFormatter.ofPattern("EEEE, 'the' dd. 'of' MMMM uuuu",
                                                    Locale.ENGLISH)
                    )
);

Isso resultaria

2020-12-18
Friday, the 18. of December 2020

No caso de estar lidando com um DatePicker datePicker, você pode receber valores selecionados por getYear(), getMonth()e getDayOfMonth(), em seguida, criar um

LocalDate localDate = LocalDate.of(datePicker.getYear(),
                                   datePicker.getMonth(), 
                                   datePicker.getDayOfMonth());

e, em seguida, basta adicionar um dia por localDate.plusDays(1);