0

I'm parsing a date in with dd-MM-yyyy format and returning in seconds (dividing it by 1000). The problem comes when I convert it to Unix Time Stamp, because it converts this seconds to the previous day. I will explain with my code and an example:

private fun String.toTimestamp(): String {
    val dateFormat = SimpleDateFormat("dd-MM-yyyy", Locale.getDefault())
    return (dateFormat.parse(this).time / 1000).toString
}

If the date is 01/02/2019 (2nd February 2019), this method returns 1548975600. If you convert it to a date (I'm using this page) it returns 01/31/2019 @ 11:00pm (UTC). I've tried adding hour, minutes and seconds, even adding the time zone, but it always returns the day before.

Another example: 13-02-2019 > 1550012400 > 02/12/2019 @ 11:00pm (UTC)

The date comes from a DatePicker, but if I create it in the next way it returns the correct day:

(Date().time / 1000).toString()

I've tried with the system's language in Spanish and in English, and changing the Locale to Locale.ENGLISH and Locale("es", "ES") and the results are the same.

Any suggestions?

Óscar
  • 1,143
  • 1
  • 19
  • 38
  • What time zone your device is on? – Keyang Feb 13 '19 at 10:18
  • Spanish, but I've tried also with `Locale.ENGLISH`, `Locale("es", "ES")` and with another device with the system language in English and the results are the same. – Óscar Feb 13 '19 at 10:19
  • 1
    It is not todo with locale but to do with your device time zone. Spain is current in GMT+1 which is 1 hour ahead of UTC. Thus 13-02-2019 00:00:00 in Spain is 12-02-2019 23:00:00 in UTC. – Keyang Feb 13 '19 at 10:24
  • By dd-MM-yyyy you loose the +0300 etc for example. – ares777 Feb 13 '19 at 10:25
  • As an aside consider throwing away the long outmoded and notoriously troublesome `SimpleDateFormat` and friends, and adding [ThreeTenABP](https://github.com/JakeWharton/ThreeTenABP) to your Android project in order to use `java.time`, the modern Java date and time API. It is so much nicer to work with. – Ole V.V. Feb 13 '19 at 10:27
  • What is the expected timestamp value? The time at midnight (00:00) UTC?? – Ole V.V. Feb 13 '19 at 10:28
  • What does your date picker return? A `Date`? A `String`? Three `int`s for year, month and day? Or…? Asking so that we can avoid doing more conversions than necessary. – Ole V.V. Feb 13 '19 at 10:46
  • @OleV.V. I'm trying to get the correct milliseconds of the `Date` I'm introducing as parameter. But when I convert this milliseconds applying the Unix format, I obtain a `Date` corresponding to the previous day. – Óscar Feb 13 '19 at 10:58

2 Answers2

1

java.time and ThreeTenABP

In Java syntax:

private static final DateTimeFormatter dateFormatter
        = DateTimeFormatter.ofPattern("dd-MM-uuuu");

public static final String toTimestamp(String dateString) {
    long epochSecond = LocalDate.parse(dateString, dateFormatter)
            .atStartOfDay(ZoneOffset.UTC)
            .toEpochSecond();
    return String.valueOf(epochSecond);
}

Let’s try it out:

    System.out.println(toTimestamp("13-02-2019"));

1550016000

Check this value on the Epoch Unix Time Stamp Converter that you linked to:

02/13/2019 @ 12:00am (UTC)

SimpleDateFormat is notoriously troublesome and along with Date long outdated. Instead I use java.time, the modern Java date and time API. This forces us to give time zone or offset explicitly. In this case as the predefined constant ZoneOffset.UTC. Which in turn makes sure we get the correct result and thus solves your problem. A further minor advantages is it gives us seconds since the epoch so we don’t need the funny-looking division by 1000.

Imports I used were:

import org.threeten.bp.LocalDate;
import org.threeten.bp.ZoneOffset;
import org.threeten.bp.format.DateTimeFormatter;

Question: Can I use java.time on Android?

Yes, java.time works nicely on older and newer Android devices. It just requires at least Java 6.

  • In Java 8 and later and on newer Android devices (from API level 26) the modern API comes built-in. In this case import from the java.time package (not org.threeten.bp).
  • In Java 6 and 7 get the ThreeTen Backport, the backport of the modern classes (ThreeTen for JSR 310; see the links at the bottom).
  • On (older) Android use the Android edition of ThreeTen Backport. It’s called ThreeTenABP. And make sure you import the date and time classes from org.threeten.bp with subpackages.

Links

Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • I'm using this way (`AndroidThreeTen` library) adding `hh:mm:ss` and it works perfectly but when hours are from 13 to 23 I receive this exception: `DateTimeParseException: Text '31-12-2019 23:59:59' could not be parsed: Invalid value for ClockHourOfAmPm (valid values 1 - 12): 23`. How can I set PM or 24 hours format? – Óscar Feb 13 '19 at 11:25
  • You probably just need uppercase `HH` for hour of day from 00 through 23 (lowercase `hh` is for hour within AM or PM, from 01 through 12). – Ole V.V. Feb 13 '19 at 11:29
  • Of course, what a mistake! Now it works perfect, thank you! – Óscar Feb 13 '19 at 11:47
-1
//convert seconds to date try below function
public static String convertSecondsToDate(Long date) {
    try {
        long dateInMiliseconds = date *1000;
        Calendar calendar = Calendar.getInstance();
        calendar.setTimeInMillis(dateInMiliseconds);
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat("dd-MM-yyyy");
        return simpleDateFormat.format(calendar.getTime());
    } catch (Exception e) {
        return "";
    }
}
Firzan Shaikh
  • 515
  • 1
  • 6
  • 12