Java virknes uz datums konversija

Kāds ir labākais veids, kā pārvērst String formātā '2. janvāris 2010' uz Date Java?

Galu galā es gribu sadalīt mēnesi, dienu un gadu kā veselos skaitļus, lai es varētu izmantot

Date date = new Date();
date.setMonth()..
date.setYear()..
date.setDay()..
date.setlong currentTime = date.getTime();

pārvērst datumu laikā.

Risinājums

Tas ir sarežģītais veids, un šīs java.util.Date iestatīšanas metodes ir atceltas kopš Java 1.1 (1997). Vienkārši formatējiet datumu, izmantojot SimpleDateFormat, izmantojot formāta paraugu, kas atbilst ievades virknei.

Jūsu konkrētajā gadījumā "2010. gada 2. janvāris" kā ievades virkne:

  1. "Janvāris" ir pilns teksta mēnesis, tāpēc tam izmantojiet MMMM šablonu.
  2. "2" ir īsa mēneša diena, tāpēc tai izmantojiet d rakstu.
  3. "2010" ir četrciparu gads, tāpēc tam izmantojiet yyyy modeli.
String string = "January 2, 2010";
DateFormat format = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH);
Date date = format.parse(string);
System.out.println(date); // Sat Jan 02 00:00:00 GMT 2010

Ievērojiet, cik svarīgs ir skaidri norādītais Locale arguments. Ja to izlaidīsiet, tiks izmantota noklusējuma vietne, kas ne vienmēr ir angļu valoda, kas izmantota ievades virknes mēneša nosaukumā. Ja locale nesakrīt ar ievades virkni, tad jūs mulsinoši saņemsiet java.text.ParseException, pat ja formāta modelis šķiet derīgs.

Lūk, izraksts no javadoc, kurā uzskaitīti visi pieejamie formāta paraugi:

Letter  Date or Time Component  Presentation        Examples
------  ----------------------  ------------------  -------------------------------------
G       Era designator          Text                AD
y       Year                    Year                1996; 96
Y       Week year               Year                2009; 09
M/L     Month in year           Month               July; Jul; 07
w       Week in year            Number              27
W       Week in month           Number              2
D       Day in year             Number              189
d       Day in month            Number              10
F       Day of week in month    Number              2
E       Day in week             Text                Tuesday; Tue
u       Day number of week      Number              1
a       Am/pm marker            Text                PM
H       Hour in day (0-23)      Number              0
k       Hour in day (1-24)      Number              24
K       Hour in am/pm (0-11)    Number              0
h       Hour in am/pm (1-12)    Number              12
m       Minute in hour          Number              30
s       Second in minute        Number              55
S       Millisecond             Number              978
z       Time zone               General time zone   Pacific Standard Time; PST; GMT-08:00
Z       Time zone               RFC 822 time zone   -0800
X       Time zone               ISO 8601 time zone  -08; -0800; -08:00

Ņemiet vērā, ka šabloni ir atkarīgi no mazajiem un lielajiem burtiem un ka četru vai vairāk rakstzīmju teksta šabloni ir pilnā formā; citādi tiek izmantota īsā vai saīsinātā forma, ja tāda ir pieejama. Tāpēc, piemēram, MMMMM vai vairāk nav nepieciešams.

Šeit ir daži derīgu SimpleDateFormat paraugu piemēri, lai analizētu doto virkni līdz datumam:

Input string                            Pattern
------------------------------------    ----------------------------
2001.07.04 AD at 12:08:56 PDT           yyyy.MM.dd G 'at' HH:mm:ss z
Wed, Jul 4, '01                         EEE, MMM d, ''yy
12:08 PM                                h:mm a
12 o'clock PM, Pacific Daylight Time    hh 'o''clock' a, zzzz
0:08 PM, PDT                            K:mm a, z
02001.July.04 AD 12:08 PM               yyyyy.MMMM.dd GGG hh:mm aaa
Wed, 4 Jul 2001 12:08:56 -0700          EEE, d MMM yyyy HH:mm:ss Z
010704120856-0700                       yyMMddHHmmssZ
2001-07-04T12:08:56.235-0700            yyyy-MM-dd'T'HH:mm:ss.SSSZ
2001-07-04T12:08:56.235-07:00           yyyy-MM-dd'T'HH:mm:ss.SSSXXX
2001-W27-3                              YYYY-'W'ww-u

Svarīgi atzīmēt, ka SimpleDateFormat nav neierobežo pavedienu drošību. Citiem vārdiem sakot, nekad nevajadzētu deklarēt un piešķirt to kā statisku vai gadījuma mainīgo un pēc tam atkārtoti izmantot to dažādās metodēs/ritmos. Tas vienmēr jāveido pilnīgi jauns metodes lokālajā darbības jomā.


Java 8 atjauninājums

Ja izmantojat Java 8 vai jaunāku versiju, izmantojiet DateTimeFormatter (arī šeit, noklikšķiniet uz saites, lai apskatītu visus iepriekš definētos formatētājus un pieejamos formātu paraugus; pamācība ir pieejama šeit). Šī jaunā API ir iedvesmojusies no JodaTime.

String string = "January 2, 2010";
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("MMMM d, yyyy", Locale.ENGLISH);
LocalDate date = LocalDate.parse(string, formatter);
System.out.println(date); // 2010-01-02

Piezīme: ja jūsu formāta paraugs satur arī laika daļu, tad izmantojiet LocalDateTime#parse(text, formatter), nevis LocalDate#parse(text, formatter). Un, ja jūsu formāta paraugs satur arī laika zonu, tad tā vietā izmantojiet ZonedDateTime#parse(text, formatter).

Lūk, izraksts no javadoc, kurā uzskaitīti visi pieejamie formāta paraugi:

Symbol  Meaning                     Presentation  Examples
------  --------------------------  ------------  ----------------------------------------------
G       era                         text          AD; Anno Domini; A
u       year                        year          2004; 04
y       year-of-era                 year          2004; 04
D       day-of-year                 number        189
M/L     month-of-year               number/text   7; 07; Jul; July; J
d       day-of-month                number        10

Q/q     quarter-of-year             number/text   3; 03; Q3; 3rd quarter
Y       week-based-year             year          1996; 96
w       week-of-week-based-year     number        27
W       week-of-month               number        4
E       day-of-week                 text          Tue; Tuesday; T
e/c     localized day-of-week       number/text   2; 02; Tue; Tuesday; T
F       week-of-month               number        3

a       am-pm-of-day                text          PM
h       clock-hour-of-am-pm (1-12)  number        12
K       hour-of-am-pm (0-11)        number        0
k       clock-hour-of-am-pm (1-24)  number        0

H       hour-of-day (0-23)          number        0
m       minute-of-hour              number        30
s       second-of-minute            number        55
S       fraction-of-second          fraction      978
A       milli-of-day                number        1234
n       nano-of-second              number        987654321
N       nano-of-day                 number        1234000000

V       time-zone ID                zone-id       America/Los_Angeles; Z; -08:30
z       time-zone name              zone-name     Pacific Standard Time; PST
O       localized zone-offset       offset-O      GMT+8; GMT+08:00; UTC-08:00;
X       zone-offset 'Z' for zero    offset-X      Z; -08; -0830; -08:30; -083015; -08:30:15;
x       zone-offset                 offset-x      +0000; -08; -0830; -08:30; -083015; -08:30:15;
Z       zone-offset                 offset-Z      +0000; -0800; -08:00;

Ņemiet vērā, ka tam ir vairāki iepriekš definēti formatētāji populārākiem paraugiem. Tā vietā, piemēram, DateTimeFormatter.ofPattern("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH);, jūs varētu izmantot DateTimeFormatter.RFC_1123_DATE_TIME. Tas ir iespējams, jo, atšķirībā no SimpleDateFormat, tie ir droši pret vītnēm. Tādējādi, ja nepieciešams, jūs varētu definēt arī savu.

Konkrētam ievades virknes formātam nav nepieciešams izmantot skaidru DateTimeFormatter: standarta ISO 8601 datumu, piemēram, 2016-09-26T17:44:57Z, var analizēt tieši ar LocalDateTime#parse(text), jo tas jau izmanto ISO_LOCAL_DATE_TIME formatētāju. Līdzīgi LocalDate#parse(text) analizē ISO datumu bez laika komponenta (sk. ISO_LOCAL_DATE), un ZonedDateTime#parse(text) analizē ISO datumu ar nobīdi un laika zonu (sk. ISO_ZONED_DATE_TIME).

Komentāri (4)

Ak jā, atkal diskusija par Java datumu. Lai veiktu manipulācijas ar datumu, mēs izmantojam Date, Calendar, GregorianCalendar un SimpleDateFormat. Piemēram, kā ievadi izmantojiet savu janvāra datumu:

Calendar mydate = new GregorianCalendar();
String mystring = "January 2, 2010";
Date thedate = new SimpleDateFormat("MMMM d, yyyy", Locale.ENGLISH).parse(mystring);
mydate.setTime(thedate);
//breakdown
System.out.println("mydate -> "+mydate);
System.out.println("year   -> "+mydate.get(Calendar.YEAR));
System.out.println("month  -> "+mydate.get(Calendar.MONTH));
System.out.println("dom    -> "+mydate.get(Calendar.DAY_OF_MONTH));
System.out.println("dow    -> "+mydate.get(Calendar.DAY_OF_WEEK));
System.out.println("hour   -> "+mydate.get(Calendar.HOUR));
System.out.println("minute -> "+mydate.get(Calendar.MINUTE));
System.out.println("second -> "+mydate.get(Calendar.SECOND));
System.out.println("milli  -> "+mydate.get(Calendar.MILLISECOND));
System.out.println("ampm   -> "+mydate.get(Calendar.AM_PM));
System.out.println("hod    -> "+mydate.get(Calendar.HOUR_OF_DAY));

Pēc tam ar to var manipulēt, izmantojot, piemēram:

Calendar now = Calendar.getInstance();
mydate.set(Calendar.YEAR,2009);
mydate.set(Calendar.MONTH,Calendar.FEBRUARY);
mydate.set(Calendar.DAY_OF_MONTH,25);
mydate.set(Calendar.HOUR_OF_DAY,now.get(Calendar.HOUR_OF_DAY));
mydate.set(Calendar.MINUTE,now.get(Calendar.MINUTE));
mydate.set(Calendar.SECOND,now.get(Calendar.SECOND));
// or with one statement
//mydate.set(2009, Calendar.FEBRUARY, 25, now.get(Calendar.HOUR_OF_DAY), now.get(Calendar.MINUTE), now.get(Calendar.SECOND));
System.out.println("mydate -> "+mydate);
System.out.println("year   -> "+mydate.get(Calendar.YEAR));
System.out.println("month  -> "+mydate.get(Calendar.MONTH));
System.out.println("dom    -> "+mydate.get(Calendar.DAY_OF_MONTH));
System.out.println("dow    -> "+mydate.get(Calendar.DAY_OF_WEEK));
System.out.println("hour   -> "+mydate.get(Calendar.HOUR));
System.out.println("minute -> "+mydate.get(Calendar.MINUTE));
System.out.println("second -> "+mydate.get(Calendar.SECOND));
System.out.println("milli  -> "+mydate.get(Calendar.MILLISECOND));
System.out.println("ampm   -> "+mydate.get(Calendar.AM_PM));
System.out.println("hod    -> "+mydate.get(Calendar.HOUR_OF_DAY));
Komentāri (1)

Strādājot ar SimpleDateFormat klasi, ir svarīgi atcerēties, ka Date nav thread-safe un vienu Date objektu nevar koplietot ar vairākiem pavedieniem.

Turklāt ir liela atšķirība starp "m" un "M", kur mazo burtu lieto minūtēm, bet lielo burtu lieto mēnesim. Tas pats ir ar "d" un "D". Tas var radīt smalkas kļūdas, kuras bieži vien netiek pamanītas. Sīkāku informāciju skatiet Javadoc vai Guide to Convert String to Date in Java.

Komentāri (2)