__DATE__转换为YYYY-MM-DD

本文介绍如何使用NSString处理__DATE__,将其转换为标准的YYYY-MM-DD日期格式,适用于iOS开发中的日期格式转换操作。

//获取编译日期,转化为"YYYY-MM-DD"形式
- (NSString *)GetCompiledDate_yyyymmdd
{
    NSString *dateStr = nil;
    static char _year[4] = {0};
    static char _month[2] = {0};
    static char _day[2] = {0};
    static const char * _monthE[] =
    {
        "Jan",
        "Feb",
        "Mar",
        "Apr",
        "May",
        "Jun",
        "Jul",
        "Aug",
        "Sep",
        "Oct",
        "Nov",
        "Dec",
    };
    const char * _date = __DATE__;
    
    memcpy(_year, _date + 7, 4);
    int year = atoi(_year);
    memcpy(_day, _date + 4, 2);
    int day = atoi(_day);
    
    int monthNum = 0;
    for(int i = 0; i < 12; i++)
    {
        if(memcmp(_monthE[i], _date, 3) == 0)
        {
            monthNum = i+1;
            break;
        }
    }
    _month[0] = monthNum / 10 % 10 + '0';
    _month[1] = monthNum % 10 + '0';
    int month = atoi(_month);
    
    dateStr = [NSString stringWithFormat:@"%04d-%02d-%02d",year,month,day];

   return dateStr;
}

<think> 我们已知错误是由于日期类型比较时类型不匹配导致的。根据用户反馈,`plan_repay_date`是DATE类型(格式为yyyy-mm-dd),而比较的另一方可能是通过运算得到的日期值,可能存在类型不一致问题。 在原始SQL中: `plan_repay_date < TO_DATE((${bizdate}-1), 'yyyy-mm-dd')` 这里,`${bizdate}`是一个字符串(如'2023-01-01'),然后进行`${bizdate}-1`的操作,这本身是不合法的(字符串不能减1)。因此,我们需要先转换`${bizdate}`为日期,然后进行日期的减法运算。 另外,虽然`plan_repay_date`是DATE类型,但是`TO_DATE((${bizdate}-1), ...)`这个表达式整体可能因为`${bizdate}-1`这个操作而变得无效。 因此,正确的做法是: 1. 将`${bizdate}`转换为日期类型。 2. 然后使用日期函数减去1天。 3. 再与`plan_repay_date`(已经是DATE类型)进行比较。 在DataWorks中,我们可以使用`DATE_SUB`函数来实现日期的减法。 修改后的条件部分: `plan_repay_date < DATE_SUB(TO_DATE(${bizdate}, 'yyyy-mm-dd'), 1)` 注意:由于`plan_repay_date`已经是DATE类型,而`DATE_SUB`返回的也是DATE类型,因此两者可以直接比较。 但是,错误提示中提到了DATEDATETIME类型,所以我们需要确认`act_repay_time`的类型。在第二个条件中: `DATE_FORMAT(act_repay_time,'%Y-%m-%d')>'${bizdate}'` 这里,`act_repay_time`可能是DATETIME类型,所以使用了`DATE_FORMAT`转换为字符串再比较。这种做法是安全的,因为转换成了字符串(格式一致)。 然而,我们也可以统一使用日期函数来避免隐式转换问题。例如,将`act_repay_time`转换DATE类型然后与日期值比较。 所以,我们可以将条件修改为: ```sql SUM( CASE WHEN ( ( plan_repay_date < DATE_SUB(TO_DATE(${bizdate}, 'yyyy-mm-dd'), 1) AND cust_repay_state = 'NORMAL' ) OR ( plan_repay_date < DATE_SUB(TO_DATE(${bizdate}, 'yyyy-mm-dd'), 1) AND cust_repay_state = 'REPAID' AND TO_DATE(act_repay_time) > TO_DATE(${bizdate}, 'yyyy-mm-dd') -- 注意:这里将act_repay_time转换DATE类型 ) ) THEN principal_amt END ) ``` 但是,注意第二个条件中,我们使用`TO_DATE(act_repay_time)`将DATETIME转换DATE类型,然后与一个DATE类型进行比较。 另外,我们也可以使用`CAST(act_repay_time AS DATE)`来进行转换。 总结修改点: 1. 用`DATE_SUB(TO_DATE(${bizdate}, 'yyyy-mm-dd'), 1)`代替原来的`TO_DATE((${bizdate}-1), ...)` 2. 将`act_repay_time`转换DATE类型再比较(使用`TO_DATE`或`CAST`) 由于DataWorks支持MaxCompute SQL,在MaxCompute中,我们可以使用`DATEADD`函数来减去一天,但是注意参数顺序。不过,MaxCompute也支持`DATE_SUB`(在MaxCompute 2.0中支持,且语法类似Hive)。 在MaxCompute SQL中,更常用的日期减法是使用`DATEADD`,但注意`DATEADD`是增加(正数为增加,负数为减少)或者使用`DATEPART`相关函数。 但是,根据MaxCompute文档,我们可以使用: `date_sub(TO_DATE(${bizdate}, 'yyyy-mm-dd'), 1)` 或者 `DATEADD(TO_DATE(${bizdate}, 'yyyy-mm-dd'), -1, 'dd')` 为了代码清晰,建议使用`date_sub`。 另外,注意在MaxCompute中,`TO_DATE`函数返回的是日期类型,而`DATE_SUB`函数返回的也是日期类型。 因此,修改后的SQL为: ```sql SUM( CASE WHEN ( ( plan_repay_date < DATE_SUB(TO_DATE(${bizdate}, 'yyyy-mm-dd'), 1) AND cust_repay_state = 'NORMAL' ) OR ( plan_repay_date < DATE_SUB(TO_DATE(${bizdate}, 'yyyy-mm-dd'), 1) AND cust_repay_state = 'REPAID' AND CAST(act_repay_time AS DATE) > TO_DATE(${bizdate}, 'yyyy-mm-dd') ) ) THEN principal_amt END ) ``` 如果`act_repay_time`是字符串类型,那么我们需要先转换为日期类型,但是根据引用[2]中的类似处理,我们假设它是日期时间类型。 如果上述修改后仍然报错,请检查数据类型是否一致。如果`plan_repay_date`不是DATE类型,则需要转换,但用户已经明确它是DATE类型(格式yyyy-mm-dd)所以不需要转换。 最后,关于引用部分: 引用[1]:描述了一个状态判断,与当前问题无关。 引用[2]:展示了在XML中处理日期比较的CDATA用法,其中使用了`date_add`函数,这提示我们可以使用日期函数进行运算。 引用[3]:展示了CASE WHEN的用法,但没有涉及日期比较。 引用[4]:说明了日期算术函数的用法,支持使用`INTERVAL`,但在MaxCompute中我们使用`DATE_SUB`即可。 因此,按照上述修改应该能解决问题。 如果问题仍然存在,请检查`${bizdate}`变量的值是否符合'yyyy-mm-dd'格式,以及字段的实际数据类型(通过DESC命令查看)。 生成的相关问题: 1. 在DataWorks中如何查看表的结构和字段类型? 2. DataWorks中日期函数`DATE_SUB`和`DATEADD`有什么区别? 3. 如何确保在SQL中正确处理日期类型避免类型错误? </think> ### 问题分析与解决方案 在 DataWorks DataStudio 中,当 `plan_repay_date` 为 **DATE 类型**(格式:yyyy-mm-dd)时,出现 `invalid operand type(s) DATE,DATETIME for operator '<'` 错误,主要原因是 **日期类型比较时的隐式转换失败**。以下是具体原因和解决方案: --- ### **错误原因分析** 1. **日期函数返回值类型不一致** `TO_DATE(${bizdate}-1, 'yyyy-mm-dd')` 返回 **DATE 类型**,但其参数 `${bizdate}-1` 试图对**字符串做减法运算**,导致: - `${bizdate}`(如 `'2023-01-01'`)是字符串类型,不支持 `-1` 操作 - 隐式转换失败触发类型冲突(DATE vs DATETIME) 2. **日期精度差异** 即使 `plan_repay_date` 是 DATE 类型,`TO_DATE()` 函数的参数若包含非法操作,可能返回异常类型值。 --- ### **解决方案** #### 步骤 1:修复日期计算逻辑 使用 **DATE_SUB()** 代替字符串减法,返回合法的 DATE 类型: ```sql SUM( CASE WHEN ( ( plan_repay_date < DATE_SUB(TO_DATE(${bizdate}, 'yyyy-mm-dd'), 1) -- 正确减1天 AND cust_repay_state = 'NORMAL' ) OR ( plan_repay_date < DATE_SUB(TO_DATE(${bizdate}, 'yyyy-mm-dd'), 1) AND cust_repay_state = 'REPAID' AND CAST(act_repay_time AS DATE) > TO_DATE(${bizdate}, 'yyyy-mm-dd') -- 统一DATE类型 ) ) THEN principal_amt END ) ``` #### 步骤 2:显式统一日期类型(保险做法) 添加 **CAST()** 确保所有日期均为 DATE 类型: ```sql SUM( CASE WHEN ( ( CAST(plan_repay_date AS DATE) < DATE_SUB(TO_DATE(${bizdate}, 'yyyy-mm-dd'), 1) AND cust_repay_state = 'NORMAL' ) OR ( CAST(plan_repay_date AS DATE) < DATE_SUB(TO_DATE(${bizdate}, 'yyyy-mm-dd'), 1) AND cust_repay_state = 'REPAID' AND CAST(act_repay_time AS DATE) > TO_DATE(${bizdate}, 'yyyy-mm-dd') ) ) THEN principal_amt END ) ``` --- ### **关键修改说明** | 原错误代码 | 修改后代码 | 作用 | |-------------------------------------|-------------------------------------|----------------------------------------------------------------------| | `${bizdate}-1` | `DATE_SUB(TO_DATE(...), 1)` | 字符串无法减1,需用日期函数操作[^2] | | 无类型转换 | `CAST(plan_repay_date AS DATE)` | 显式统一为 DATE 类型,避免隐式转换失败 | | `DATE_FORMAT(act_repay_time...)` | `CAST(act_repay_time AS DATE)` | 直接转为 DATE 类型比字符串比较更高效[^3] | --- ### **验证与调试建议** 1. **单独测试日期表达式** 在 SQL 外单独运行验证: ```sql SELECT DATE_SUB(TO_DATE('${bizdate}', 'yyyy-mm-dd'), 1); -- 应返回前一天的DATE类型值 ``` 2. **检查字段元数据类型** 执行命令确认字段类型: ```sql DESC your_table_name; -- 查看plan_repay_date和act_repay_time的精确类型 ``` 3. **使用日期函数替代运算符** 始终优先使用内置函数: - `DATE_SUB(date, N)` 取代 `date - N` - `DATE_ADD(date, N)` 取代 `date + N` > ✅ **预防措施**: > 在比较日期前,**显式转换所有日期值为 DATE 类型**,避免隐式转换风险。 ---
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值