C#vs Java中的日期时间操作
我是Java新手。我有一个时间,我从一个网页,这是在“hh:mm”格式(不是24小时)。这对我来说就像一根绳子。然后,我想将这个字符串与todays date结合起来,以便生成一个我可以使用的JavaC#vs Java中的日期时间操作,java,c#,datetime,date-parsing,Java,C#,Datetime,Date Parsing,我是Java新手。我有一个时间,我从一个网页,这是在“hh:mm”格式(不是24小时)。这对我来说就像一根绳子。然后,我想将这个字符串与todays date结合起来,以便生成一个我可以使用的Javadate 在C#中: 在Java中,我尝试过: String s = "5:45 PM"; Date d = new Date(); // Which instantiates with the current date/time. String[] arr = s.split(" "); boo
date
在C#中:
在Java中,我尝试过:
String s = "5:45 PM";
Date d = new Date(); // Which instantiates with the current date/time.
String[] arr = s.split(" ");
boolean isPm = arr[1].compareToIgnoreCase("PM") == 0;
arr = arr[0].split(":");
int hours = Integer.parseInt(arr[0]);
d.setHours(isPm ? hours + 12 : hours);
d.setMinutes(Integer.parseInt(arr[1]));
d.setSeconds(0);
有没有更好的方法来实现我的目标
有没有更好的方法来实现我的目标
绝对-事实上,在.NET和Java中都是如此。在.NET中,我(有偏见地)建议使用,这样您就可以将一天中的某个时间表示为LocalTime
,精确解析您期望的模式
在Java8中,您可以对Java.time.LocalTime
执行相同的操作:
import java.time.*;
import java.time.format.*;
public class Test {
public static void main(String[] args) {
String text = "5:45 PM";
DateTimeFormatter format = DateTimeFormatter.ofPattern("h:mm a");
LocalTime time = LocalTime.parse(text, format);
System.out.println(time);
}
}
// combine with today's date
LocalDateTime combined = LocalDate.now().atTime(time);
一旦将文本解析为适当的类型,就可以将其与其他类型组合。例如,要使用今天的日期和一天中的指定时间在系统时区中获取ZoneDateTime
,可以使用:
ZonedDateTime zoned = ZonedDateTime.now().with(time);
默认情况下,这会使用系统时区和时钟,因此很难进行测试-我建议传入时钟
,以提高可测试性
(野田佳彦也提供同样的服务,但略有不同。如果您需要详细信息,请告诉我。)
我强烈建议不要使用java.util.Date
,因为它有一个糟糕的API
这里的要点是:
- 使用指定的格式解析文本
- 将文本解析为表示它所传递信息的类型:一天中的某个时间
- 将该值与另一个也应仔细指定的值相结合(根据时钟和时区)
所有这些都将产生清晰、可靠、可测试的代码。(在我看来,现有的.NET代码不符合这些要点中的任何一点。)要解析时间,您可以按照中的说明执行: 请注意,我还使用了
java.util.Locale
,因为如果不指定它,它将使用系统的默认区域设置,并且一些区域设置可以为AM/PM字段使用不同的符号。使用显式区域设置可以避免这种情况(并且默认区域设置也可以更改,即使在运行时也是如此,因此最好使用显式区域设置)
要与今天的日期组合,需要一个java.time.LocalDate
(获取日期)并与LocalTime
组合,以获取LocalDateTime
:
import java.time.*;
import java.time.format.*;
public class Test {
public static void main(String[] args) {
String text = "5:45 PM";
DateTimeFormatter format = DateTimeFormatter.ofPattern("h:mm a");
LocalTime time = LocalTime.parse(text, format);
System.out.println(time);
}
}
// combine with today's date
LocalDateTime combined = LocalDate.now().atTime(time);
然后,您可以使用另一个格式化程序格式化LocalDateTime
:
DateTimeFormatter fmt = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm");
System.out.println(combined.format(fmt));
输出为:
2017年8月16日17:45
如果要将
LocalDateTime
转换为java.util.Date
,必须注意一些细节
Ajava.util.Date
表示自1970-01-01T00:00Z
(又称Unix历元)以来的毫秒数。这是一个瞬间(一个特定的时间点)。查看更多信息
因此,同一个Date
对象可以表示不同的日期或时间,具体取决于您所处的位置:现在,在这个时刻,世界上的每个人都在同一个瞬间(自1970-01-01T00:00Z以来的毫秒数相同),但世界各地的本地日期和时间都不同
LocalDateTime
表示“本地”的概念:它是一个日期(天、月和年)和一个时间(小时、分钟、秒和纳秒),但与特定时区没有任何关系
同一个LocalDateTime
对象可以表示不同时区的不同时间点。因此,要将其转换为日期,必须定义所需的时区
一个选项是使用系统的默认时区:
// convert to system's default timezone
ZonedDateTime atDefaultTimezone = combined.atZone(ZoneId.systemDefault());
// convert to java.util.Date
Date date = Date.from(atDefaultTimezone.toInstant());
但默认值可能因系统/环境而异,甚至在运行时也可以更改。要不依赖于此并对其进行更多控制,可以使用显式区域:
// convert to a specific timezone
ZonedDateTime zdt = combined.atZone(ZoneId.of("Europe/London"));
// convert to java.util.Date
Date date = Date.from(zdt.toInstant());
请注意,我使用了欧洲/伦敦
。API使用的格式(始终为地区/城市
,如美国/圣保罗
或欧洲/柏林
)。
避免使用三个字母的缩写(如CST
或PST
),因为它们是
通过调用ZoneId.getAvailableZoneIds()
,可以获得可用时区的列表(并选择最适合您的系统的时区)
还有夏令时的一些极端情况(当一个LocalDateTime
可以存在两次或由于以下原因而不存在时)。在这种情况下,使用ZonedDateTime
可以避免这个问题)。使用SimpleDateForma classt来处理java中的每种格式。@AMallal:理想情况下,不要使用java.time
。@Jon skeet:My badWait,Jon,这并没有给我与.NET代码相同的内容。我想要有todays date,时间是我想要的字符串值。因此,对于今天的“16/08/2017 15:45”,最好将其作为日期对象,以便我可以对其执行操作。这只在转储到控制台时给出“17:45”。@MoonKnight:ADate
对象是时间上的一个瞬间。你想把它放在哪个时区<代码>日期
几乎总是使用错误的类型。我会再编辑我的答案。@MoonKnight:扩展了很多。很好。我只想要一张快照,但我同意你关于日期的所有观点。非常感谢您花时间写一份详细的回复,非常感谢。我接受你说的一切。再次感谢。回答得很好,非常感谢您抽出时间。我从中学到了很多。祝你一切顺利。@MoonKnight不客气,很高兴能帮助你!我可以推荐这一点吗?这是java.time
API的一个很好的起点。干杯您应该按原样使用Locale.ROOT
。