Skip to content

Full schema preview
initial_schema/time/time.esdl
# scalar types
scalar type DayOfWeek extending enum<Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday>;
scalar type FuzzyYear extending int64;
scalar type FuzzyMonth extending int64 {constraint expression on (__subject__ >=1 and __subject__ <=12)}
scalar type FuzzyDay extending int64 {constraint expression on (__subject__ >=1 and __subject__ <=31)}
scalar type FuzzyHour extending int64 {constraint expression on (__subject__ >=0 and __subject__ <=23)}
scalar type FuzzyMinute extending int64 {constraint expression on (__subject__ >=0 and __subject__ <=59)}
scalar type FuzzySecond extending int64 {constraint expression on (__subject__ >=0 and __subject__ <=59)}


# object types
type FuzzyTime {
    fuzzy_year: FuzzyYear;
    fuzzy_month: FuzzyMonth;
    fuzzy_day: FuzzyDay;
    fuzzy_hour: FuzzyHour;
    fuzzy_minute: FuzzyMinute;
    fuzzy_second: FuzzySecond;
    fuzzy_dow: DayOfWeek; 
    fuzzy_fmt:= (
        with Y:= <str>.fuzzy_year ?? "YYYY",
                m:= <str>.fuzzy_month ?? "MM",
                m:= m if len(m) > 1 else "0" ++ m,
                d:= <str>.fuzzy_day ?? "DD",
                d:= d if len(d) > 1 else "0" ++ d,
                H:= <str>.fuzzy_hour ?? "HH24",
                H:= H if len(H) > 1 else "0" ++ H,
                M:= <str>.fuzzy_minute ?? "MI",
                M:= M if len(M) > 1 else "0" ++ M,
                S:= <str>.fuzzy_second ?? "SS",
                S:= S if len(S) > 1 else "0" ++ S,
                dow:= <str>.fuzzy_dow ?? "ID", 
        select Y ++ "/" ++ m ++ "/" ++ d ++ "_" ++
                H ++ ":" ++ M ++ ":" ++ S ++ "_" ++
                dow       
    );

    trigger fuzzy_month_day_check after insert, update for each 
    when (exists __new__.fuzzy_month and exists __new__.fuzzy_day) 
    do ( 
        assert_exists(
            cal::to_local_date(__new__.fuzzy_year ?? 2002, __new__.fuzzy_month, __new__.fuzzy_day),
            ) 
    );
    constraint exclusive on (.fuzzy_fmt);
}

Scalar types

DayOfWeek

DayOfWeek代表一星期內七天。

scalar type DayOfWeek extending enum<Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday>;

FuzzyYear

FuzzyYear直接extending int64

scalar type FuzzyYear extending int64;

FuzzyMonth

FuzzyMonth extending int64後,再加上一個constraint,限制其值只能為1~12。

scalar type FuzzyMonth extending int64 {
    constraint expression on (__subject__ >=1 and __subject__ <=12)
}

FuzzyDay

FuzzyDay extending int64後,再加上一個constraint,限制其值只能為1~31。

scalar type FuzzyDay extending int64 {
    constraint expression on (__subject__ >=1 and __subject__ <=31)
}

FuzzyHour

FuzzyHour extending int64後,再加上一個constraint,限制其值只能為0~23。

scalar type FuzzyHour extending int64 {
    constraint expression on (__subject__ >=0 and __subject__ <=23)
}

FuzzyMinute

FuzzyMinute extending int64後,再加上一個constraint,限制其值只能為0~59。

scalar type FuzzyMinute extending int64 {
    constraint expression on (__subject__ >=0 and __subject__ <=59)
}

FuzzySecond

FuzzySecond extending int64後,再加上一個constraint,限制其值只能為0~59。

scalar type FuzzySecond extending int64 {
    constraint expression on (__subject__ >=0 and __subject__ <=59)
}

Object types

FuzzyTime

FuzzyTime除了包含前述七個scalar typeproperty外,還加了一個fuzzy_fmt property,一個trigger及一個constraint

type FuzzyTime {
    fuzzy_year: FuzzyYear;
    fuzzy_month: FuzzyMonth;
    fuzzy_day: FuzzyDay;
    fuzzy_hour: FuzzyHour;
    fuzzy_minute: FuzzyMinute;
    fuzzy_second: FuzzySecond;
    fuzzy_dow: DayOfWeek; 
    fuzzy_fmt:= (
        with Y:= <str>.fuzzy_year ?? "YYYY",
             m:= <str>.fuzzy_month ?? "MM",
             m:= m if len(m) > 1 else "0" ++ m,
             d:= <str>.fuzzy_day ?? "DD",
             d:= d if len(d) > 1 else "0" ++ d,
             H:= <str>.fuzzy_hour ?? "HH24",
             H:= H if len(H) > 1 else "0" ++ H,
             M:= <str>.fuzzy_minute ?? "MI",
             M:= M if len(M) > 1 else "0" ++ M,
             S:= <str>.fuzzy_second ?? "SS",
             S:= S if len(S) > 1 else "0" ++ S,
             dow:= <str>.fuzzy_dow ?? "ID", 
        select Y ++ "/" ++ m ++ "/" ++ d ++ "_" ++
               H ++ ":" ++ M ++ ":" ++ S ++ "_" ++
               dow       
    );

    trigger fuzzy_month_day_check after insert, update for each 
    when (exists __new__.fuzzy_month and exists __new__.fuzzy_day) 
    do ( 
        assert_exists(
            cal::to_local_date(__new__.fuzzy_year ?? 2002, __new__.fuzzy_month, __new__.fuzzy_day),
            ) 
    );
    constraint exclusive on (.fuzzy_fmt);
}

fuzzy_fmt

fuzzy_fmtcomputed property,為一特殊的str格式來表達每個FuzzyTime object。其中??是指當該scalar type為空的set時(即<str>{}),所給予的預設值

trigger

當同時給定fuzzy_monthfuzzy_day時,我們可以透過cal::to_local_date來驗證這樣的月份與日期,是否為一有效的組合。

逐步拆解各部份語法:

  • fuzzy_month_day_check為此trigger名字,可自行定義。afterfor each中間,輸入想要trigger的類型。本例中是想要當對FuzzyTime進行insertupdate時,才會觸發trigger

    trigger fuzzy_month_day_check after insert, update for each
    

  • when為選擇性條件,當其後expressiontrue時,才會觸發trigger。其中__new__是指我們想要insertupdateobject

    when (exists __new__.fuzzy_month and exists __new__.fuzzy_day) 
    

  • do為這個trigger想要執行的內容。我們這裡使用assert_exists搭配cal::to_local_date來驗證給定的月份及日期組合是否合理。當沒有給定年份時,使用??語法指定為無間道主要劇情時間的2002年。由於我們的fuzzy_day已經被FuzzyDay限制在1~31之間,所以這個trigger可以幫我們去除掉2/302/314/316/319/3111/31等不合理的時間,至於沒有給定年份的2/29是無法生成的(因為2002年不是閏年)。如果真的要生成2/29這麼特別的日子,需強制加上年份來鑒別其是否為一合理的時間。

    do ( 
        assert_exists(
            cal::to_local_date(__new__.fuzzy_year ?? 2002, __new__.fuzzy_month, __new__.fuzzy_day),
            ) 
    );
    
    另外,當您使用略為超過合理時間的日期(如4/31),cal::to_local_date報錯訊息會和一般情況不太一樣,會貼心地提示您這個日期剛好超出合理區間。

cal::to_local_date報錯訊息

  edgedb error: InvalidValueError: cal::local_date field value out of range: 2002-04-31
  edgedb error: ConstraintViolationError: invalid FuzzyDay
    Detail: invalid scalar type 'default::FuzzyDay'

constraint

針對fuzzy_fmt property加上exclusive後,可以確保當使用FuzzyTime時,不會生成一個以上可以表達同一模糊時間的FuzzyTime object