Simply I have the following class to get my JSON body that received from remote response to deserialize to CreditCardDTO
the date recieved inside exp_date
like "0820" for 8/2010, and "0240" for 2/2040:
import com.fasterxml.jackson.annotation.JsonFormat;
import com.fasterxml.jackson.annotation.JsonProperty;
import java.util.Date;
@JsonInclude(JsonInclude.Include.NON_EMPTY)
@JsonPropertyOrder(alphabetic = true)
public class CreditCardDTO {
private String brand;
private Date expirationDate;
@JsonProperty("brand")
public String getBrand() {
return brand;
}
@JsonProperty("credit_card_type")
public CreditCardDTO setBrand(String brand) {
this.brand = brand;
return this;
}
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd'T'HH:mm:ss.SSSZ")
@JsonProperty("expirationDate")
public Date getExpirationDate() {
return expirationDate;
}
@JsonFormat(pattern = "MMyy")
@JsonProperty("exp_date")
public CreditCardDTO setExpirationDate(Date expirationDate) {
System.out.println(expirationDate);
this.expirationDate = expirationDate;
return this;
}
}
The problem that if it is before Year 2038 everything is OK, but once the data is after that critical date, it still happens, the data is back to 1941, I searched about the problem and found that it should not be happen in Java 8 : Why should a Java programmer care about year 2038 bug? , so I'm wondering what the issue here!
Jackson version 2.8.0, Java 8 for sure.
While I don't know about Jackson, i can tell you that you've taken a poor approach to handling this credit card expiration data.
Firstly you chose to roll-your-own rather than look to existing classes and standards. Always search for prior work; roll-your-own approach should be a last resort, not first. Less wild-cowboy, more judge-guided-by-precedent.
Secondly, you are using troublesome old date-time classes that are legacy, now supplanted by the java.time classes.
YearMonth
To represent a year and a month, use the YearMonth
class built into Java. The months are numbered sanely, 1-12 for January-December, unlike the legacy classes.
YearMonth ym = YearMonth.of( 2040 , 3 ) ;
By the way, you may find the Month
enum handy in your work.
YearMonth ym = YearMonth.of( 2040 , Month.MARCH ) ;
Use this YearMonth
class as your member rather than a specific date.
When comparing to a date such as today, get the YearMonth
for that date.
ZoneId z = ZoneId.of( "Asia/Amman" ) ;
LocalDate today = LocalDate.now( z ) ;
YearMonth ymToday = YearMonth.from( today ) ;
Boolean isExpired = ymToday.isAfter( ym ) ;
The ISO 8601 standard defines many practical sensible formats for representing date-time values as text.
The standard format for year-month is YYYY-MM
. So March 2040 is 2040-03
.
The java.time classes use the standard formats by default when parsing or generating strings.
Generate a string.
ym.toString()
2040-03
Parse a string.
YearMonth ym = YearMonth.parse( "2040-03" );
For both storage and presentation, always use four digits for years. The endless confusion, errors, and ambiguity is not worth saving two octets of memory/storage or half a centimeter of space on paper.