【问题标题】:Rrule Until tag data valueRrule 直到标签数据值
【发布时间】:2019-02-25 18:05:37
【问题描述】:

我正在开发一个需要 rrule 来生成下一个事件的项目。但我无法理解我需要在 rrule 的 UNTIL 标签中添加什么。

String str="RRULE:FREQ=MONTHLY;UNTIL=20190625T000000Z;INTERVAL=2;";

Idk 如何将日期转换为"20190625T000000Z"。我正在使用 rfc 2445 java 库。如果用户以字符串形式输入日期,例如:25/06/2019......我需要在 UNTIL 标记中设置此值,如上所示。如果我在 UNTIL 中设置默认值,那么它可以工作,但当我使它对用户友好时就不行了。我将用户的所有值作为开始日期、结束日期、间隔、截止日期、直到......但是我知道要什么值设置为 UNTIL。 如果有人可以帮助..提前谢谢。

【问题讨论】:

  • 这个问题并不完全清楚。我建议你花更多的时间和精力来措辞和写你的问题。此外,这不是一个随意的聊天网站,它更像是维基百科,一个问答形式的知识库。所以,请不要“idk”。花点时间正确书写完整的拼写、大写和标点符号。
  • 请了解如何使用 Stack Overflow 的 Markdown 版本格式化代码。比较简单,四个前导空格字符或反引号(GRAVE ACCENT)标记环绕。

标签: java rrule


【解决方案1】:

解析基本 ISO 8601 格式

您的输入20190625T000000Z 是标准ISO 8601 格式的“基本”变体,以UTC 表示时刻。 “基本”一词的意思是尽量减少分隔符的使用(我不推荐这样做,因为它会降低人类对字符串的可读性)。

定义格式模式以匹配输入。

String input = "20190625T000000Z";
DateTimeFormatter f = DateTimeFormatter.ofPattern( "uuuuMMdd'T'HHmmssX" );
OffsetDateTime odt = OffsetDateTime.parse( input , f );

转储到控制台。

System.out.println("odt.toString(): " + odt);

看到这个code run live at IdeOne.com

odt.toString(): 2019-06-25T00:00Z

将日期转换为时刻

如果用户以字符串形式输入日期,例如:25/06/2019……我需要在 UNTIL 标记中设置此值,如上所示

首先,将该输入字符串解析为LocalDate,表示仅日期值,没有时间和时区。

DateTimeFormatter fDateOnly = DateTimeFormatter.ofPattern( "dd/MM/uuuu" );
LocalDate ld = LocalDate.parse( "25/06/2019" , fDateOnly );

ld.toString(): 2019-06-25

至于将日期转换为时刻(在区域中具有时间或与 UTC 有偏移的日期),这比听起来更直观。

2019 年 6 月 25 日等日期代表一整天。还有一个理论上的日期。一天开始和结束的时刻在全球各地因时区而异。新的一天在日本东京开始的时间比在法国巴黎要早得多,在魁北克蒙特利尔甚至更晚。

另一个问题是一天并不总是从 00:00:00 开始。由于夏令时 (DST) 等异常情况,在某些区域的某些日期,一天的第一刻可能类似于 01:00:00。让 java.time 类确定第一时刻。

ZoneId z = ZoneId.of( "Africa/Tunis" );
ZonedDateTime zdt = ld.atStartOfDay( z );

zdt.toString(): 2019-06-25T00:00+01:00[非洲/突尼斯]

ZonedDateTime 对象代表一个特定的时刻。但它使用特定地区(时区)人们采用的挂钟时间。您的目标是 UTC 中的某个时刻。幸运的是,我们可以通过转换为 OffsetDateTime(具有与 UTC 偏移而不是时区的上下文的日期和时间)来从区域调整为 UTC。我们可以通过 ZoneOffset.UTC 常量指定 UTC(零偏移)。

OffsetDateTime odt = zdt.toOffsetDateTime().withOffsetSameInstant( ZoneOffset.UTC );

odt.toString(): 2019-06-24T23:00Z

请注意突尼斯 25 日的 00:00 是 UTC 的“昨天”24 日晚上 11 点。同一时刻,时间轴上的同一同时点,但两个不同的挂钟时间。

最后,我们需要一个“基本”ISO 8601 格式的字符串。使用我们上面定义的相同格式化程序。

DateTimeFormatter fIso8601DateTimeBasic = DateTimeFormatter.ofPattern( "uuuuMMdd'T'HHmmssX" );
String output = odt.format( fIso8601DateTimeBasic );

输出:20190624T230000Z

看到这个code run live at IdeOne.com

时区和 UTC 偏移量有什么区别?偏移量只是几个小时-分钟-秒。不多也不少,只是一个数字(嗯,三个数字)。时区更多。时区是特定地区的人们使用的偏移量的过去、现在和未来变化的历史。例如,在北美的大部分地区,偏移量每年变化两次,提前一个小时然后下降一个小时(Daylight Saving Time (DST) 的疯狂)。

提示:日期时间处理非常棘手且容易出错。如果您正在使用日历和 iCalendar 规范进行数据交换,我建议您花很长时间学习行业领先的 java.time 类的概念和实践。


关于java.time

java.time 框架内置于 Java 8 及更高版本中。这些类取代了麻烦的旧 legacy 日期时间类,例如 java.util.DateCalendarSimpleDateFormat

要了解更多信息,请参阅Oracle Tutorial。并在 Stack Overflow 上搜索许多示例和解释。规格为JSR 310

Joda-Time 项目现在位于maintenance mode,建议迁移到java.time 类。

您可以直接与您的数据库交换 java.time 对象。使用符合JDBC 4.2 或更高版本的JDBC driver。不需要字符串,不需要java.sql.* 类。

从哪里获得 java.time 类?

ThreeTen-Extra 项目通过附加类扩展了 java.time。该项目是未来可能添加到 java.time 的试验场。您可以在这里找到一些有用的类,例如IntervalYearWeekYearQuartermore

【讨论】:

  • 该解决方案很有帮助,但我不能使用 LocalDate 类来解析日期。我可以改用 Date 类吗?
  • 不,Date 不适用于日期,它适用于 UTC 时间。而Date 是另一个可怕的遗留类,被java.time.Instant 取代。 LocalDate 类内置于 Java 中。可以用,用import java.time.* ;
  • 好的,我知道了。感谢您的帮助。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-08-31
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多