年月日相关常识

介绍有关年、月、日等时间单位方面的知识让学生借助观察年历来认识时间单位年、月、日,然后介绍平年、闰年的判断方法,以及拳头记忆法(一三五七八十腊,三十一天永不差)和大月歌诀记忆法,最后是算出平年、闰年全年的天数。

为什么八月有31天?大月小月的由来 ?

人们都有这样的常识,阳历有大小月之分,即阳历月份有这样的规定:“4月、6月、9月及11月有30天,其余的月份有31天,2月例外,只有28天。”

月份的大小,始于罗马帝国恺撒时代。当时恺撒派人修订历法,制订了儒略历法,决定凡有特别宗教意义的月份31天,不重要的月份30天。因此,取名门神的1月,以战神为名的3月,为表示尊敬恺撒大帝而取名的7月,都有31天。因为2月是处死犯人的月份,属不吉的时间,所以只有29天。恺撒大帝的继任人奥古斯的生日在8月。为了和恺撒等同起来,他要求把8月也加成31天。为了要使8月有31天,他便从2月再借来一天,把2月减少到28天。又为避免3个大月的月份连在一起,又规定9月及11月各有30天,把10月及12月加长到31天。

闰年是怎么回事,二月为什么是28天?


在公历(格里历)纪年中,有闰日的年份叫闰年,一般年份365天,闰年为366天。由于地球绕太阳运行周期为365天5小时48分46秒(合365.24219天)即一回归年,公历把一年定为365天,叫做平年。所余下的时间约为四年累计一天,加在二月里,所以平常年份每年365天,二月为28天,闰年为366天,二月为29天。因此,每400年中有97个闰年,闰年在2月末增加一天,闰年366天。 闰年的计算方法:公元纪年的年数可以被四整除,即为闰年;被100整除而不能被400整除为平年;被100整除也可被400整除的为闰年。如2000年是闰年,而1900年不是。
可以这样判断平、闰年
因为一个多位数,如果后两位数能被4整除,那么这个数就能被4整除,所以,只要把年份的后两位数除以4,进行判断即可。如:1998年是平年还是闰年?用98÷4=24……2,所以1998年是平年。若是整百年的年份,只用年份的前两位数除以4即可,(被除数和除数同时缩小100倍,商不变。)如:2400年是平年还是闰年?用24÷4=6,所以2400年是闰年。。二月既不是大月,也不是小月,它是一个特殊的月份通常把二月份有28天的这一年叫做平年,有29天的那一年叫做闰年(板书平、闰年)。

<think>我们正在处理一个关于动态拼接SQL查询条件的问题,特别是针对年月日字段。用户希望根据给定的年月日条件动态构建查询。根据引用[1],我们看到了一个使用QueryWrapper的例子,其中通过apply方法使用date_format函数来匹配日期。这提示我们可以使用类似的方法来处理日期字段的匹配。用户的需求是动态拼接,所以我们需要考虑如何根据不同的输入条件(可能只有年、只有年月、年月日都有)来构建查询条件。思路:1.我们可以接收三个参数:年、月、日(可能为空)2.根据参数的存在情况,动态生成SQL条件。例如:-如果只有年,则查询该年的所有数据。-如果有年和月,则查询该年该月的数据。-如果有年、月、日,则查询该年该月该日的数据。在SQL中,我们可以使用YEAR(),MONTH(),DAY()函数来提取日期部分的各个成分,然后与给定的参数进行比较。但是,注意引用[1]中使用了date_format函数,我们也可以使用这个函数,根据传入的参数格式来动态生成格式字符串。另一种方法是使用数据库的日期函数(如YEAR(),MONTH(),DAY())分别比较,这样更清晰。例如:-如果只给定了年,则条件为:YEAR(create_time)=2023-如果给定了年和月,则条件为:YEAR(create_time)=2023ANDMONTH(create_time)=4-如果给定了年、月、日,则条件为:YEAR(create_time)=2023ANDMONTH(create_time)=4ANDDAY(create_time)=25但是,这种方法可能会因为数据库的不同而有所差异,但主流数据库都支持这些函数。另外,引用[2]展示了使用CASE语句的例子,但这里我们不需要使用CASE,因为我们是动态拼接条件,而不是在结果集中进行条件判断。引用[3]提到了存储引擎的选择,但和当前问题无关。在Java中使用MyBatis-Plus的QueryWrapper,我们可以这样动态构建:假设我们有一个方法,接收三个参数:year,month,day(都是Integer类型,可能为null)```javapublicList<User>queryByDate(Integeryear,Integermonth,Integerday){QueryWrapper<User>qw=newQueryWrapper<>();if(year!=null){qw.eq("YEAR(create_time)",year);}if(month!=null){qw.eq("MONTH(create_time)",month);}if(day!=null){qw.eq("DAY(create_time)",day);}returnuserMapper.selectList(qw);}```但是,这里需要注意,直接使用数据库函数可能会导致索引失效(如果create_time上有索引的话)。为了利用索引,我们可以使用范围查询。另一种更高效的方式是使用范围查询,特别是当有索引时:-如果只有年,我们可以查询该年的第一天到最后一天之间的数据。-如果有年月,我们可以查询该月的第一天到最后一天之间的数据。-如果有年月日,则查询该天的数据。具体实现:我们可以根据参数构建开始日期和结束日期:```javapublicList<User>queryByDate(Integeryear,Integermonth,Integerday){QueryWrapper<User>qw=newQueryWrapper<>();if(year==null){//如果没有年份,则无法构建条件,这里可以根据需求处理,比如返回空或者不添加条件//这里假设必须要有年份,否则不查询returnCollections.emptyList();}LocalDatestartDate,endDate;if(month==null){//只有年startDate=LocalDate.of(year,1,1);endDate=LocalDate.of(year,12,31);}elseif(day==null){//有年月startDate=LocalDate.of(year,month,1);endDate=startDate.with(TemporalAdjusters.lastDayOfMonth());}else{//年月日都有startDate=LocalDate.of(year,month,day);endDate=startDate;}//将LocalDate转换为数据库日期格式的字符串(假设数据库存储的是日期时间类型,我们只需要日期部分,但比较时包括时间的话,需要将结束日期加一天然后使用小于)//注意:数据库中的create_time是datetime类型,所以我们使用>=startDate和<endDate.plusDays(1)qw.ge("create_time",startDate.atStartOfDay());qw.lt("create_time",endDate.plusDays(1).atStartOfDay());returnuserMapper.selectList(qw);}```这种方法可以利用索引(如果create_time上有索引),效率更高。但是,用户可能希望更灵活,可能只有月份和日期(没有年份)?根据常识,没有年份的日期条件是不常见的,所以这里我们假设年份是必须的,月份和日期可选。如果用户没有年份,我们也可以处理,但是需要根据需求来定。这里我们假设年份必须提供。另外,如果用户希望使用字符串拼接的方式(比如在XML中写动态SQL),我们也可以提供MyBatis的动态SQL写法。在MyBatis的MapperXML文件中:```xml<selectid="selectByDate"resultType="User">SELECT*FROMuser<where><iftest="year!=nullandmonth==nullandday==null">create_timeBETWEEN#{startDate}AND#{endDate}<!--这里需要计算出该年的开始和结束日期,可以在Java代码中计算然后传入,或者在SQL中计算,但SQL中计算可能复杂--></if><!--其他情况类似--></where></select>```但是,在XML中计算日期范围比较麻烦,所以推荐在Java代码中计算出开始和结束时间,然后作为参数传入。因此,我们可以这样设计:1.在Service层中,根据year,month,day计算出startDateTime和endDateTime(注意:结束日期要加一天,然后小于这个值)。2.将这两个时间传给Mapper。Mapper接口:```javaList<User>selectByDate(@Param("startDateTime")DatestartDateTime,@Param("endDateTime")DateendDateTime);```XML:```xml<selectid="selectByDate"resultType="User">SELECT*FROMuserWHEREcreate_time>=#{startDateTime}ANDcreate_time<#{endDateTime}</select>```然后Service层方法:```javapublicList<User>queryByDate(Integeryear,Integermonth,Integerday){if(year==null){//处理没有年份的情况,比如返回空或者抛出异常,或者查询所有?根据需求//这里我们返回空列表returnCollections.emptyList();}LocalDatestartDate,endDate;if(month==null){startDate=LocalDate.of(year,1,1);endDate=LocalDate.of(year,12,31);}elseif(day==null){startDate=LocalDate.of(year,month,1);endDate=startDate.with(TemporalAdjusters.lastDayOfMonth());}else{startDate=LocalDate.of(year,month,day);endDate=startDate;}//转换为Date类型(或者LocalDateTime)LocalDateTimestartDateTime=startDate.atStartOfDay();LocalDateTimeendDateTime=endDate.plusDays(1).atStartOfDay();returnuserMapper.selectByDate(startDateTime,endDateTime);}```这样,我们通过范围查询,并且使用了索引,效率较高。总结:动态拼接日期查询条件,推荐使用范围查询,先根据输入的年月日计算出查询的日期范围(开始日期和结束日期),然后使用create_time>=开始日期ANDcreate_time<结束日期(注意结束日期是次日零点)。最后,根据用户问题,生成相关问题:</think>### 动态拼接年月日SQL查询条件 根据需求,您需要根据年月日字段动态拼接SQL查询条件。以下是几种常见实现方案: #### 方案1:使用日期函数直接拼接(推荐) ```java public List<User> dynamicQuery(Integer year, Integer month, Integer day) { QueryWrapper<User> qw = new QueryWrapper<>(); if (year != null) { qw.apply("YEAR(create_time) = {0}", year); } if (month != null) { qw.apply("MONTH(create_time) = {0}", month); } if (day != null) { qw.apply("DAY(create_time) = {0}", day); } return userMapper.selectList(qw); } ``` **说明**: - `YEAR()/MONTH()/DAY()` 函数直接提取日期部分 - 各条件独立判断,支持单年/单月/单日查询 - 参数为 `null` 时自动忽略该条件[^1] #### 方案2:日期范围查询(适合带索引字段) ```java public List<User> dynamicRangeQuery(Integer year, Integer month, Integer day) { QueryWrapper<User> qw = new QueryWrapper<>(); LocalDateTime start = LocalDateTime.of( Optional.ofNullable(year).orElse(1900), Optional.ofNullable(month).orElse(1), Optional.ofNullable(day).orElse(1), 0, 0 ); LocalDateTime end = start; if (day == null && month != null) end = start.with(TemporalAdjusters.lastDayOfMonth()); else if (month == null) end = start.with(TemporalAdjusters.lastDayOfYear()); else end = start.plusDays(1); qw.between("create_time", start, end); return userMapper.selectList(qw); } ``` **特点**: - 利用 `BETWEEN` 语句提高索引命中率 - 自动计算日期范围(如查询整月时自动匹配当月所有天数) #### 方案3:动态SQL拼接(XML方式) ```xml <!-- Mapper.xml --> <select id="dynamicSearch" resultType="User"> SELECT * FROM user <where> <if test="year != null"> AND YEAR(create_time) = #{year} </if> <if test="month != null"> AND MONTH(create_time) = #{month} </if> <if test="day != null"> AND DAY(create_time) = #{day} </if> </where> </select> ``` **调用方式**: ```java Map<String, Object> params = new HashMap<>(); params.put("year", 2023); params.put("month", 6); userMapper.dynamicSearch(params); ``` ### 关键注意事项 1. **索引优化**:对 `create_time` 字段建立索引可显著提升性能 ```sql CREATE INDEX idx_create_time ON user(create_time); ``` 2. **时区处理**:确保数据库时区与应用时区一致 3. **空值处理**:建议使用包装类 `Integer` 代替 `int` 避免空指针 4. **跨年处理**:当年份为空时,需明确是否需要限制查询时间范围 > 方案1在多数场景下最简洁高效,方案2适合数据量查询,方案3便于复杂条件扩展[^1][^3]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值