Java'da 'January 2, 2010' biçimindeki bir String
i bir Date
e dönüştürmenin en iyi yolu nedir?
Nihayetinde, ay, gün ve yılı tamsayı olarak ayırmak istiyorum, böylece
Date date = new Date();
date.setMonth()..
date.setYear()..
date.setDay()..
date.setlong currentTime = date.getTime();
tarihi saate dönüştürmek için.
Bu zor bir yoldur ve bu java.util.Date
ayarlayıcı yöntemleri Java 1.1'den (1997) beri kullanımdan kaldırılmıştır. Basitçe, giriş dizesiyle eşleşen bir biçim deseni kullanarak SimpleDateFormat
kullanarak tarihi biçimlendirin.
Giriş dizesi olarak "January 2, 2010" özel durumunuzda:
MMMM
kalıbını kullanınd
kalıbını kullanın.yyyy
kalıbını kullanın.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
Açık Locale
argümanının önemine dikkat edin. Bunu atlarsanız, girdi dizesinin ay adında kullanıldığı gibi İngilizce olması gerekmeyen varsayılan yerel ayarı kullanacaktır. Yerel ayar giriş dizesiyle eşleşmezse, biçim deseni geçerli görünse bile kafa karıştırıcı bir şekilde bir java.text.ParseException
alırsınız.
Burada'javadoc]1'dan ilgili bir alıntı, mevcut tüm biçim kalıplarını listeliyor:
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
Kalıpların büyük/küçük harfe duyarlı olduğunu ve dört veya daha fazla karakterden oluşan metin tabanlı kalıpların tam formu temsil ettiğini unutmayın; aksi takdirde, varsa kısa veya kısaltılmış bir form kullanılır. Yani örneğin MMMMM
veya daha fazlası gereksizdir.
Burada, verilen bir dizeyi tarihe ayrıştırmak için geçerli SimpleDateFormat
kalıplarının bazı örnekleri verilmiştir:
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
Önemli bir not, SimpleDateFormat
ın **iş parçacığı güvenli olmadığıdır. Başka bir deyişle, onu asla statik veya örnek değişken olarak bildirmemeli ve atamamalı ve daha sonra farklı yöntemlerden / iş parçacıklarından yeniden kullanmamalısınız. Her zaman yöntemin yerel kapsamında yepyeni oluşturmalısınız.
Java 8 veya daha yeni bir sürüm kullanıyorsanız, DateTimeFormatter
kullanın (ayrıca burada, önceden tanımlanmış tüm biçimlendiricileri ve mevcut biçim kalıplarını görmek için bağlantıya tıklayın; öğretici burada mevcuttur). Bu yeni API JodaTime'den esinlenmiştir.
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
Not: Biçim deseniniz saat kısmını da içeriyorsa LocalDateTime#parse(text, formatter)
yerine LocalDate#parse(text, formatter)
kullanın. Ve biçim deseniniz saat dilimini de içeriyorsa, bunun yerine ZonedDateTime#parse(text, formatter)
kullanın.
Burada'javadoc]3'tan ilgili bir alıntı, mevcut tüm biçim kalıplarını listeliyor:
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;
Daha popüler kalıplar için birkaç önceden tanımlanmış biçimlendiriciye sahip olduğunu unutmayın. Örneğin DateTimeFormatter.ofPattern("EEE, d MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
yerine DateTimeFormatter.RFC_1123_DATE_TIME
kullanabilirsiniz. Bu mümkündür, çünkü SimpleDateFormat
ın aksine, iş parçacığı güvenlidirler. Bu nedenle, gerekirse kendiniz de tanımlayabilirsiniz.
Belirli bir girdi dizesi biçimi için, açık bir DateTimeFormatter
kullanmanıza gerek yoktur: 2016-09-26T17:44:57Z gibi standart bir ISO 8601 tarihi, zaten ISO_LOCAL_DATE_TIME
biçimlendiricisini kullandığından, doğrudan LocalDateTime#parse(text)
ile ayrıştırılabilir. Benzer şekilde, LocalDate#parse(text)
bir ISO tarihini zaman bileşeni olmadan ayrıştırır (bkz. ISO_LOCAL_DATE
) ve ZonedDateTime#parse(text)
bir ISO tarihini bir ofset ve saat dilimi ekleyerek ayrıştırır (bkz. ISO_ZONED_DATE_TIME
).
Ah evet, yine Java Tarihi tartışması. Tarih manipülasyonu ile başa çıkmak için Date, Calendar, GregorianCalendar ve SimpleDateFormat kullanırız. Örneğin Ocak tarihinizi girdi olarak kullanmak gibi:
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));
Sonra bunu aşağıdaki gibi bir şeyle manipüle edebilirsiniz:
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));
SimpleDateFormat sınıfı ile uğraşırken, Date'in iş parçacığı güvenli olmadığını ve tek bir Date nesnesini birden fazla iş parçacığı ile paylaşamayacağınızı hatırlamak önemlidir.
Ayrıca "m" ile "M" arasında büyük fark vardır; burada dakikalar için küçük harf, aylar için büyük harf kullanılır. Aynı şey "d" ve "D" için de geçerlidir. Bu, genellikle gözden kaçan ince hatalara neden olabilir. Daha fazla ayrıntı için Javadoc veya Java'da Dizeyi Tarihe Dönüştürme Kılavuzu bölümlerine bakın.