Check if a document is expired
BlinkID does not report expiry status directly. Instead, it returns the expiry date that it read from the document, and you decide whether the document is expired by comparing that date against today.
Two result fields drive this logic:
dateOfExpiry: a date result with optional numericyear,month, anddayparts, plus the printedoriginalStringand asuccessfullyParsedflag.dateOfExpiryPermanent: a boolean that istruewhen the document never expires.
Determining expiry
Apply the following logic to the scanning result:
- If
dateOfExpiryPermanentistrue, the document never expires, so treat it as not expired. - If
dateOfExpirywas not parsed into numeric parts (noyear), you cannot determine the expiry status. - Otherwise, build a date from
year,month, anddayand compare it against today.
- Web (TS)
- Android (Kotlin)
- iOS (Swift)
type ExpiryStatus = "expired" | "valid" | "unknown";
function checkExpiry(result): ExpiryStatus {
if (result.dateOfExpiryPermanent) {
return "valid";
}
const expiry = result.dateOfExpiry;
if (!expiry?.successfullyParsed || expiry.year === undefined) {
return "unknown";
}
// Month is 1-12, so subtract one for the JS Date constructor.
const expiryDate = new Date(expiry.year, (expiry.month ?? 1) - 1, expiry.day ?? 1);
return expiryDate < new Date() ? "expired" : "valid";
}
blinkId.addOnResultCallback((result) => {
console.log("Expiry status:", checkExpiry(result));
void blinkId.destroy();
});
import java.time.LocalDate
enum class ExpiryStatus { EXPIRED, VALID, UNKNOWN }
fun checkExpiry(result): ExpiryStatus {
if (result.dateOfExpiryPermanent == true) {
return ExpiryStatus.VALID
}
val expiry = result.dateOfExpiry
if (expiry?.successfullyParsed != true || expiry.year == null) {
return ExpiryStatus.UNKNOWN
}
// Month is 1-12, which matches LocalDate.
val expiryDate = LocalDate.of(expiry.year, expiry.month ?: 1, expiry.day ?: 1)
return if (expiryDate.isBefore(LocalDate.now())) ExpiryStatus.EXPIRED else ExpiryStatus.VALID
}
onScanningSuccess = { result ->
println("Expiry status: ${checkExpiry(result)}")
}
enum ExpiryStatus {
case expired, valid, unknown
}
func checkExpiry(_ result) -> ExpiryStatus {
if result.dateOfExpiryPermanent == true {
return .valid
}
guard let expiry = result.dateOfExpiry,
expiry.successfullyParsed,
let year = expiry.year else {
return .unknown
}
// Month is 1-12, which matches DateComponents.
var components = DateComponents()
components.year = year
components.month = expiry.month ?? 1
components.day = expiry.day ?? 1
guard let expiryDate = Calendar.current.date(from: components) else {
return .unknown
}
return expiryDate < Date() ? .expired : .valid
}
onScanCompleted: { resultState in
guard let result = resultState.scanningResult else { return }
print("Expiry status:", checkExpiry(result))
}
Handling the unknown case
When the expiry date cannot be parsed, fall back to the printed text in originalString rather than rejecting the document outright.
This lets you surface the raw expiry text to a reviewer or to the user for manual confirmation.
- Web (TS)
- Android (Kotlin)
- iOS (Swift)
blinkId.addOnResultCallback((result) => {
if (!result.dateOfExpiryPermanent && !result.dateOfExpiry?.successfullyParsed) {
console.log("Could not parse expiry. Printed text:", result.dateOfExpiry?.originalString?.latin?.value);
}
void blinkId.destroy();
});
onScanningSuccess = { result ->
if (result.dateOfExpiryPermanent != true && result.dateOfExpiry?.successfullyParsed != true) {
println("Could not parse expiry. Printed text: ${result.dateOfExpiry?.originalString?.value}")
}
}
onScanCompleted: { resultState in
guard let result = resultState.scanningResult else { return }
if result.dateOfExpiryPermanent != true && result.dateOfExpiry?.successfullyParsed != true {
print("Could not parse expiry. Printed text:", result.dateOfExpiry?.originalString?.value ?? "")
}
}