0

I'm using SQLite for my database, but the result for date_logged is showing me an unexpected value, like 1731279600000, instead of the date I entered (e.g., 2024-11-12). I used H2 for my database previously, and it worked fine there, but it's not working correctly in SQLite. How can I fix this?

@Column(nullable = false)
@JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd")
private LocalDate dateLogged;

This is the code in my Log entity

@PostMapping("/logs")
public Log createLog(@RequestBody Map<String, Object> logData) {
    return logService.createLogEntry(
            (String) logData.get("username"),
            (String) logData.get("project_name"),
            Double.valueOf(logData.get("hours_logged").toString()),
            LocalDate.parse((String) logData.get("date_logged"))
    );
}

LogController

public Log createLogEntry(String username, String projectName, Double hoursLogged, LocalDate dateLogged) {
    User user = userRepository.findByUsername(username);
    if (user == null) throw new RuntimeException("User not found");
    Log log = new Log();
    log.setUser(user);
    log.setProjectName(projectName);
    log.setHoursLogged(hoursLogged);
    log.setDateLogged(dateLogged);
    return logRepository.save(log);
}

LogService

1 Answer 1

3

1731279600000 is the unix timestamp. Take a look: https://www.unixtimestamp.com. So it is one of the ways to store the date you provided which is 2024-11-10.

Talking a bit about sqlite, unlike other databases, it does not have date types. Instead it can be one of:

SQLite does not have a storage class set aside for storing dates and/or times. Instead, the built-in Date And Time Functions of SQLite are capable of storing dates and times as TEXT, REAL, or INTEGER values:

TEXT as ISO8601 strings ("YYYY-MM-DD HH:MM:SS.SSS").
REAL as Julian day numbers, the number of days since noon in Greenwich on November 24, 4714 B.C. according to the proleptic Gregorian calendar.
INTEGER as Unix Time, the number of seconds since 1970-01-01 00:00:00 UTC.

full docs: https://www.sqlite.org/datatype3.html

In your scenario, you can create custom setters.

So when you set it(dateLogged): it saves the value in database as unix timestamp and sets the one you want So when spring sets it(dateLoggedUnix): it sets the value and already sets the one that you want in locadate.

Example:

@Entity
class Log {
    private String projectName;
    private Double hoursLogged;
    @Transient // jpa one to make database ignore this field
    private LocalDate dateLogged;
    private long dateLoggedUnix;

    public void setDateLoggedUnix(int dateLoggedUnix) {
        this.dateLoggedUnix = dateLoggedUnix;
        this.dateLogged = Instant.ofEpochSecond(dateLoggedUnix)
                .atZone(ZoneId.systemDefault())
                .toLocalDate();
    }

    public void setDateLogged(LocalDate dateLogged) {
        this.dateLogged = dateLogged;
        this.dateLoggedUnix = dateLogged
                .atStartOfDay(ZoneId.systemDefault())
                .toEpochSecond();
    }
    // other noraml gettters and setter
}

Remember, @JsonFormat(shape = JsonFormat.Shape.STRING, pattern = "yyyy-MM-dd") is only for jackson library, not JPA.

Also as an alternative, you might find this answer interesting https://stackoverflow.com/a/77771796/10880357

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.