0

I have a date of type "long" and want to validate it. It was converted elsewhere from an xml File.

  • xml File date: 2018-01-35T00:00+02:00
  • long date: 1517695200000L

This date (2018-01-35 as yyyy-mm-dd) should be an invalid date.

I already tried the solution given in: How to sanity check a date in java

I converted the long to a Date but that already changed the date from 2018-01-35 to 2018-02-04, so there was no exception thrown. This was the complete code:

long longDate = 1517695200000L;
Date date = new Date(longDate);
System.out.println("long: " + longDate);
System.out.println("Date: " + date);
Calendar cal = Calendar.getInstance();
cal.setLenient(false);
cal.setTime(date);

try {
    cal.getTime();
} catch (Exception e) {
    LOG.error("invalid date");
    return false;
}

Is there any possibilty to convert a long to a Date without this "self-validation"? Or does anybody have another idea? Thanks in advance.

Lea
  • 261
  • 5
  • 14
  • 4
    You will have to clarify how do you transform your long to a Date to get 2018-01-35?? –  Nov 02 '17 at 14:17
  • 2
    Assuming this `long` value is obtained via `Date.getTime()`, it's just "milliseconds since the Unix epoch" - so it's always valid. Indeed, `Date` itself would always be valid, too... it sounds like you need to be more strict on the *text* conversion, which you haven't shown. 2018-01-35 is a text representation, not a long representation. – Jon Skeet Nov 02 '17 at 14:18
  • maybe the long is 20180135L –  Nov 02 '17 at 14:18
  • Please provide an [MCVE] – Jens Nov 02 '17 at 14:19
  • Are you using the long outdated `Date` class? Why? I recommend the modern `LocalDate` instead. It’s much nicer to work with. – Ole V.V. Nov 02 '17 at 14:20
  • 2
    You could use SimpleDateFormat with setLenient(false). Read [this](https://stackoverflow.com/questions/1905551/make-simpledateformat-parse-fail-on-invalid-dates-e-g-month-is-greater-than) – marco Nov 02 '17 at 14:22
  • 1
    Well, your `long` formatted date will always be valid then, it could be before or after a specific date, but it can't be formatted like you said ` 2018-01-35` because the logic to transform at date into a `long` is simply the number of (milli)seconds since a specific date (depends on the system used) – AxelH Nov 02 '17 at 14:27
  • I didn't mean that the value of the variable of type long or date is 2018-01-35. It was just an example to show what I mean with "self-validation" which happens when converting long to date. – Lea Nov 02 '17 at 14:29
  • How did you print the date to see the result after conversion to long? – AxelH Nov 02 '17 at 14:32
  • @AxelH Debugging. I converted from long to Date. – Lea Nov 02 '17 at 14:34
  • 1
    Please provide a [mcve] of you test, with input and output expected, this is usually easier to understand. – AxelH Nov 02 '17 at 14:35
  • 1
    Thanks for the code. As Jon Skeet and AxelH already said in comments, your `longDate` will always be a valid date. It can never represent January 35, 2018 or such non-existing date. You may want to validate that it is within some realistic range, though (like 5 mio BCE to 5 mio AD or within the last 6 weeks). – Ole V.V. Nov 02 '17 at 14:43
  • 1
    @marco, these days no one should use the long outdated and notoriously troublesome `SimpleDateFormat` class. If you want to parse a date string in order to validate it (which can be a fine idea), use `DateTimeFormatter`, the modern and much nicer replacement, with `ResolverStyle.STRICT`. – Ole V.V. Nov 02 '17 at 14:46
  • Thanks @Lea for the value, but how did you get that `Long` from the XML Date ? Once you have the `long` version of the `date` because it was already "truncated" into a correct date, you can't validate it, you only can validate it from the `String` representation. – AxelH Nov 02 '17 at 14:50
  • @AxelH the program has a function to convert xmlTime to long...I cannot change the function so I just have this long variable to work with – Lea Nov 02 '17 at 14:54
  • 2
    Well, unless you can get that value as a `String`, you are stuck with a problem.... Sorry. This result is from a `SimpleDateFormat(...).parse()` that's accept that wrong value and truncate it... if this formatter was set to lenient = false, it would throw an exception. – AxelH Nov 02 '17 at 14:57

2 Answers2

4

The long is a number of seconds since an arbitrary date (1970). So it will always be a valid date. For the past you might consider a start of the world. Or the year 10000 as incredible and unformatable with yyyy.

Joop Eggen
  • 107,315
  • 7
  • 83
  • 138
3

In order to validate the date, you need the string from your XML. Then it’s quite simple when you know how:

    String xmlFileDate = "2018-01-35T00:00+02:00";
    try {
        OffsetDateTime.parse(xmlFileDate);
    } catch (DateTimeParseException dtpe) {
        System.err.println("Invalid date");
    }

I am exploiting the fact that your date-time string is in ISO 8601 format, the format that the modern Java date and time classes parse as their default.

After the date-time has been converted to 1517695200000L, there is no way to tell that it came from an invalid date-time string, so at that point there is nothing you can do. As Jon Skeet and AxelH already said in comments, a long will always represent a valid date.

Basil Bourque
  • 303,325
  • 100
  • 852
  • 1,154
Ole V.V.
  • 81,772
  • 15
  • 137
  • 161
  • @Lea, unfortunatly, as you said, you can only work with that long but that long has already been "corrupted", you have to override that XML parser or check if you can't configure the parser to invalidate a date (as it should...). – AxelH Nov 02 '17 at 15:03
  • in this scenario the format is ISO-8859-1 but it could also be UTF-8...depends on the xml file given. – Lea Nov 02 '17 at 15:04
  • 2
    @Lea, those are character encodings or charsets. If the XML file can be read correctly in both cases, just until the point where you have got `2018-01-35T00:00+02:00`, then you don’t need to care, the date-time string format will still be ISO 8601. – Ole V.V. Nov 02 '17 at 15:06