/**
 * LocalStorage data access class
 * @param {string} prefix Key prefix
 * @param {string} timeSplit Separator between timestamp and stored data
 */
var DAO = function (prefix, timeSplit) {
    this.prefix = prefix;
    this.timeSplit = timeSplit || "|-|";
}
```javascript
// Prototype method
DAO.prototype = {
    constructor: DAO,
    // Operation status
    status: {
        SUCCESS: 0,     // Success
        FAILURE: 1,     // Failure
        OVERFLOW: 2,    // Overflow
        TIMEOUT: 3      // Expired
    },
    // Local storage object
    storage: localStorage || window.localStorage,
    /**
     * Get the real key value with prefix
     * @param key Data field identifier
     */
    getKey: function (key) {
        return this.prefix + key;
    },
    /**
     * Add (or update) data
     * @param key Data field identifier
     * @param value Data value
     * @param callback Callback function
     * @param time Expiration time
     */
    set: function (oriKey, value, callback, time) {
        let status = this.status.SUCCESS; // Default to success
        let key = this.getKey(oriKey);
        try{
            time = new Date(time).getTime() || time.getTime(); // Get expiration timestamp
        }catch(e){
            time = new Date().getTime() + 1000 * 60 * 60 * 24 * 30; // Default to one month if no expiration time is set
        }
        try{
            this.storage.setItem(key, time + this.timeSplit + value); // Add (or update) data to local storage
        }catch(e){
            status = this.status.OVERFLOW; // Overflow occurred
        }
        callback && callback.call(this, status, key, value); // Execute callback and pass in parameters
    },
    /**
     * Get data
     * @param key Data field identifier
     * @param callback Callback function
     */
    get: function (oriKey, callback) {
        let key = this.getKey(oriKey);
        let status = this.status.SUCCESS;    // Get data status
        let value = null;    // Get data value
        try{
            value = this.storage.getItem(key); // Get data from local storage
        }catch(e){
            status = this.status.FAILURE; // Failed to get data
            value = null;
        }
        // If data is successfully retrieved
        if (status !== this.status.FAILURE) {
            let index = value.indexOf(this.timeSplit);
            let timeSplitLen = this.timeSplit.length;
            let time = value.slice(0, index); // Get the timestamp
            // Check if the data is not expired
            if(new Date(1 * time).getTime() > new Date().getTime() || time === 0) {
                value = value.slice(index + timeSplitLen); // Get the data value
            }else {
                value = null; // Data has expired, delete the data
                status = this.status.TIMEOUT;
                this.remove(key);
            }
        }
        callback && callback.call(this, status, value); // Execute callback
        return value; // Return the result value
    },
    /**
    * Delete data
    * @param key Data field identifier
    * @param callback Callback function
    */
    remove: function (oriKey, callback) {
        let status = this.status.FAILURE; // Set the default status to failure
        let key = this.getKey(oriKey);
        let value = null;
        try {
            value = this.storage.getItem(key); // Get the data value
        }catch(e){
            // Data does not exist, no operation is taken
        }
        if(value){ // If the data exists
            try{
                // Delete the data
                this.storage.removeItem(key);
                status = this.status.SUCCESS;
            }catch(e) {
                // Data deletion failed, no operation is taken
            }
        }
        // Execute callback and pass in parameters, if successful, pass in the deleted data value
        let param = status > 0 ? null : value.slice(value.indexOf(this.timeSplit) + this.timeSplit.length);
        callback && callback.call(this, status, param);
    }
};