简体   繁体   中英

Best way to record date with mandatory year and month, and only optional day

I am building a php/sql (Laravel) app for managing magazines. Each magazine has a property of date of issue. Unfortunately, this date may be either in the format of year-month-day or year-month for monthly periodicals. When retrieving a magazine, I need to get its date of issue as is, meaning year-month only for monthlies, and year-month-day for the rest.

The only solution that I can think of is add another column of boolean type, for example is_monthly , and use that to determine the issue date format. But I would like to know if there is a better way to store date in a database as only year and month, without a day.

You can store as 3 columns (year/month/date):

SqlFiddleDemo

CREATE TABLE magazine(title VARCHAR(100), `year` INT NOT NULL,
                      month TINYINT NOT NULL, day TINYINT NULL);

INSERT INTO magazine
VALUES ('aaa', 2015, 10, 16), ('bbb', 2015, 11, NULL);

SELECT 
    title,
    CASE WHEN day IS NULL THEN CONCAT(`year`, '-' , month)
         ELSE CONCAT(`year`, '-' , month, '-', day)
     END AS `publish_date`
FROM magazine

Output:

╔════════╦══════════════╗
║ title  ║ publish_date ║
╠════════╬══════════════╣
║ aaa    ║ 2015-10-16   ║
║ bbb    ║ 2015-11      ║
╚════════╩══════════════╝

Yes, I'd prefer going with your approach of having a boolean column say is_monthly as it would give you greater control over your approach in the long run.

You can set your date as a Carbon instance and define a mutator say setIssueDateAttribute($date) in your model and default the day part of your date to say the first of the month in case there is no day value available, ie in case is_monthly is set to true .

This way, you would be able to simply store the date as is in the database without any hassle and when you wish to display only the month and the year of the date, you could put it as

$this->attributes['issue_date'] = Carbon::setToStringFormat('F, Y');

in your `getIssueDateAttribute($date) accessor.

You can find more about setting attributes here:

Laravel Tutorial on Dates, Scope and Mutators

Accessors and Mutators Laravel Documentation

If you are using MySQL, then it supports incomplete dates as part of the date datatype. This might solve your problem.

However, I might suggest that you store the date-of-issue as a string representation of the date. I imagine that this could vary by magazine. Then use a date to store the "functional" date, used for calculations. The functional date could just use a canonical day-of-the-month (such as "1") for the issue date.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM