I am pulling a Date from a database, reassigning it as a TextField, and then toString() it, but the date comes out "Thurs 0900 OCT 12 2015" when all I need is MM/DD/YYYY format. How do I change the format?
Date myDatabaseDate = someDBGetMethod();
TextField myDateTF = new TextField()
myDateTF.setCaption("My date is: ");
myDateTF.setValue(myDatabaseDate).toString());
myDateTF.setReadOnly(true);
FormLayout fLayout = new FormLayout();
addComponent(fLayout);
fLayout.addComponent(myDateTF);
What's happening: Thu Oct 22 12:19:04 CDT 2015
What I want: 22/10/2015
Thank you in advance!
Examples make the most sense to me as I am very new to vaadin.
Vaadin Not The Problem
If trying to display a String representation of a date-time object, then Vaadin is not a part of the problem. Vaadin offers a widget, DateField, for the user to pick a date-time value. You do not need that widget for simply displaying the string representation. For display, use a TextField as you described in the Question.
So the problem is how to generate that String representation.
First be aware that Java includes two classes named "Date":
java.util.Date
java.sql.Date
Confusingly, they are not parallel. The util one is a date plus a time-of-day in UTC. The sql one is meant to represent a date-only, but is poorly designed; as a hack it subclasses the util one but alters the time-of-day to be 00:00:00.000. These old date-time classes in early Java are a bad mess.
From a database you should be receiving the latter, java.sql.Date for a date-only stored value. If you were storing date-time values, then you should be getting java.sql.Timestamp objects from your JDBC driver.
java.time LocalDate
As java.sql.Date is one of the old clunky date-time classes bundled with early Java, we should convert to the new classes found in the java.time framework built into Java 8 and later. See Tutorial.
For a date-only value, java.time offers the LocalDate class. The "Local" in the name refers to any locality rather than a particular locality. It represents the vague idea of a date, but is not tied to the timeline. A date starts earlier in Paris than in Montréal, for example. If you care about exact moments on the timeline, you would be using java.sql.Timestamp rather than java.sql.Date.
Converting from java.sql.Date to java.time.LocalDate is an easy one-liner, as a conversion method is provided for you.
LocalDate localDate = myJavaSqlDate.toLocalDate();
Going the other way is just as easy, when storing data into the database.
java.sql.Date myJavaSqlDate = java.sql.Date.valueOf( localDate );
With a LocalDate in hand, you can call on the java.time.format package to format a string localized for easy reading by the user. Specify the Locale expected by the user.
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDate( FormatStyle.FULL ).withLocale( Locale.CANADA_FRENCH );
String output = localDate.format( formatter );
Example output:
dimanche 1 novembre 2015
ZonedDateTime
Let’s consider if you did get a java.sql.Timestamp rather than java.sql.Date.
We can convert from a java.sql.Timestamp to a Instant, a moment on the timeline in UTC.
Instant instant = myTimestamp.toInstant();
Next, assign a time zone.
ZoneId zoneId = ZoneId.of( "America/Montreal" );
ZonedDateTime zdt = ZonedDateTime.ofInstant( instant , zoneId);
We use the java.time.format package to create the String representation. Note the chained calls, the second one setting a specific Locale. If not specified, your JVM’s current default Locale is implicitly applied. Better to be explicit.
DateTimeFormatter formatter = DateTimeFormatter.ofLocalizedDateTime ( FormatStyle.FULL ).withLocale ( Locale.CANADA_FRENCH );
String output = zdt.format ( formatter );
Example output:
dimanche 1 novembre 2015 2 h 24 EST
java.util.date object does not contain any information how to present himself as String. That's because in different locations communities writes dates in different ways. So Java separates operations on dates from printing them out on the screen.
What you are missing in your code is a DateFormat.
Date myDatabaseDate = new Date(2014,10,10);
DateFormat format = DateFormat.getDateInstance(DateFormat.SHORT, Locale.UK);
TextField myDateTF = new TextField();
myDateTF.setCaption("My date is: ");
myDateTF.setValue(format.format(myDatabaseDate));
myDateTF.setReadOnly(true);
layout.addComponent(myDateTF);
I would strongly encourage you however to use Java 8 Dates API since Java 7 Dates API is a total mess. You can read more about that here What's wrong with Java Date & Time API?
Related
I want to get the 4-digit year from today.
I have a variable def todayDate = new Date() in my controller.
I googled to see how to do it. It pointed me to this page.
https://docs.groovy-lang.org/latest/html/groovy-jdk/java/util/Date.html
There is a method called toYear()
Actually, none of the methods in this document works. The Date class in this document is not the same Date class in the controller for sure.
Did Google show me the wrong document? What is the correct way to get the 4-digit year from a Date()?
I was reading and trying to understand all the comments and checking the links. I think I get what is going on here.
When I declare a Date variable in Grails, it is a java.util.Date. If I google how to work with the Date, this gets confusing. The methods that process the Date are not from the java.util.Date class. Majority of the java.util.Date methods are deprecated. The methods you can find from google are actually coming from the org.codehaus.groovy:groovy-dateutil:3.0.9 Groovy date enhancement package.
So, the Date is a java.util.Date but the methods are from the enhancement package.
tl;dr
You said:
I want to get the 4-digit year from today.
String.valueOf( LocalDate.now().getYear() ) // Java syntax.
2022
Avoid legacy classes
The java.util.Date class is terribly flawed. Along with Calendar and the other legacy date-time classes, these were years ago supplanted by the modern java.time classes defined in JSR 310.
Sun, Oracle, and the JCP community all gave up on these legacy classes. I suggest you do the same.
Year
(Forgive the Java syntax as I do not know Groovy.)
If all you want is the year, use Year class.
Year currentYear = Year.now( z ) ;
int y = currentYear.getValue() ;
LocalDate#getYear
For a date-only value, use LocalDate.
Time zone
Determining the current date requires a time zone. For any given moment, the date varies around the globe by time zone.
(Again, Java syntax.)
ZoneId z = ZoneId.of( "America/Edmonton" ) ; // Or, ZoneId.systemDefault() ;
LocalDate today = LocalDate.now( z ) ;
int year = today.getYear() ;
I do not see all these methods in your Groovy API documentation. Perhaps I do not know how that doc works. The classes listed here are built into Java 8 and later.
I want to compare string representations of weeks, e.g. week "01/17" is before "02/17" and after "52/16".
The following code throws an exception, I guess because my string doesn't hint at the exact day of each week. However, I don't care - it could all be Mondays or Thursdays or whatever:
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("ww/YY", Locale.GERMANY);
LocalDate date1 = formatter.parse(str1, LocalDate::from);
Do I need to modify the parser? Or parse to some other format? Unfortunatley there is no object like YearMonth for weeks...
One solution would be to always default to the same day, say the Monday. You could build a custom formatter for that:
DateTimeFormatter fmt = new DateTimeFormatterBuilder()
.appendPattern("ww/YY")
.parseDefaulting(ChronoField.DAY_OF_WEEK, 1)
.toFormatter(Locale.GERMANY);
You can now build LocalDates representing the Monday of the given week:
LocalDate d1 = LocalDate.parse("01/17", fmt);
LocalDate d2 = LocalDate.parse("52/16", fmt);
System.out.println(d1.isAfter(d2));
which prints true because 01/17 is after 52/16.
I wasn't able to find a way for this to work with the DateTimeFormatter class, but I would like to suggest a different approach.
The Threeten Extra library contains a number of classes that were deemed too specific to include in the java.time library. One of them is the YearWeek class you mention.
Your problem can be solved by parsing the week-number and year manually from the input-string and then invoking the YearWeek creator-method like this:
YearWeek yw = YearWeek.of(year, monthOfYear);
tl;dr
YearWeek.parse( "2017-W01" )
ISO 8601
Or parse to some other format?
Yes, use another format.
Use the standard ISO 8601 formats when serializing date-time values to text. The standard includes support for week dates.
For a year-week that would be four year digits, a hyphen, a W, and two digits for the week of the year.
2017-W01
Get clear on your definition of a “week”. The ISO 8601 definition is that:
The Week # 1 contains the first Thursday of the year, and
Runs Monday-Sunday.
So years run either 52 or 53 weeks long. And note that under this definition, the first few days of the year may be in the prior year when week-numbering. Likewise, the last few days of the year may be in the following year when week-numbering.
If you want to indicate a particular day within that week, append a hyphen and a single digit running 1-7 for Monday-Sunday.
Tip: To see ISO 8601 week numbers by default on your computer, you may need to adjust your OS setting. For example, on macOS set System Preferences > Language & Region > Calendar > ISO 8601 to make apps such as Calendar.app to display week numbers with this standard definition.
2017-W01-7
By the way, a couple of similar representations:
An ordinal date meaning the year and the day-of-year-number running from 1-366 is year, a hyphen, and a three-digit number: 2017-123
Month-Day without year is two hyphens, month number, hyphen, and day-of-month number: --01-07
Note that the use of Locale as seen in the Question is irrelevant here with the standard ISO 8601 formats.
YearWeek
Unfortunatley there is no object like YearMonth for weeks...
Ahhh, but there is such a class.
For a class to directly represent the idea of a week-year, see the correct Answer by Henrik. That Answer shows the ThreeTen-Extra library’s class YearWeek.
The YearWeek class can directly parse and generate strings in standard format.
YearWeek yw = YearWeek.parse( "2017-W01" );
You can compare the YearWeek objects with methods: compareTo, equals, isBefore, isAfter.
yw.isBefore( thatYw )
The ThreeTen-Extra project offers other classes such as YearQuarter that you may find useful.
I need to convert Swift Date object to date ticks string like "/Date(631148400000+0100)/".
The following link tells me how to convert date ticks string to Date object but not the vice-versa:
How to convert date like \/Date(1440156888750-0700)\/ to something that Swift can handle?
How can I do that?
Thanks in advance.
From Stand-Alone JSON Serialization:
DateTime values appear as JSON strings in the form of "/Date(700000+0500)/", where the first number (700000 in the example provided) is the number of milliseconds in the GMT time zone, regular (non-daylight savings) time since midnight, January 1, 1970. The number may be negative to represent earlier times. The part that consists of "+0500" in the example is optional and indicates that the time is of the Local kind - that is, should be converted to the local time zone on deserialization. If it is absent, the time is deserialized as Utc. The actual number ("0500" in this example) and its sign (+ or -) are ignored.
And from Use JSON.NET to parse json date of format Date(epochTime-offset)
... In this screwy format, the timestamp portion is still based solely on UTC. The offset is extra information. It doesn't change the timestamp. You can give a different offset, or omit it entirely and it's still the same moment in time.
So the number of ticks is the number of milliseconds since Januar 1, 1970 GMT. Adding a time zone specification would only change how the
date is presented locally in .NET, and one can simply omit that part
when generating a JSON date string:
extension Date {
var jsonDate: String {
let ticks = lround(timeIntervalSince1970 * 1000)
return "/Date(\(ticks))/"
}
}
Example:
print(Date().jsonDate) // /Date(1481446227993)/
Background: I'm building an app with Angular JS as web interface and Rails API. The problem I am having is passing a date from Angular to Rails.
Issue: I have a form with a Date of Birth date field, when a user inputs his DOB say March 1st, 1985, Angular interprets it as 1985-03-01 00:00 +0800 (if you're in Hong Kong or Singapore) and sends a request to Rails. The first thing Rails does with it is to convert it to UTC, which means the datetime is now 1985-02-28 16:00 UTC. Therefore, when the date is saved to the database date column, it becomes Feb 28, 1985.
Solution for now: What I'm doing now is on Angular side, I get the Timezone offset hours and add it to the date, so instead of 1985-03-01 00:00 +0800, it is now 1985-03-01 08:00 +0800. When Rails get it, it converts to 1985-03-01 00:00 UTC and so saves the correct date to db. However, I believe this is a better alternative to tackle this issue.
Thinking about parsing just the date in Rails, yet the params[:dob] I see is already UTC by the time I get it. Would love to know if there is a better practice than my current solution. Thank you for any comment and feedback.
This problem is actually quite common, and stems from two separate but related issues:
The JavaScript Date object is misnamed. It's really a date + time object.
The JavaScript Date object always takes on the characteristics of the time zone for the environment in which it is running in.
For a date-only value like date-of-birth, the best solution to this problem is to not send a full timestamp to your server. Send just the date portion instead.
First, add 12 hours to the time, to use noon instead of midnight. This is to avoid issues with daylight saving time in time zones like Brazil, where the transition occurs right at midnight. (Otherwise, you may run into edge cases where the DOB comes out a day early.)
Then output the date portion of the value, as a string in ISO format (YYYY-MM-DD).
Example:
var dt = // whatever Date object you get from the control
dt.setHours(dt.getHours() + 12); // adjust to noon
var pad = function(n) { return (n < 10 ? '0' : '') + n; }
var dob = dt.getFullYear() + '-' + pad(dt.getMonth()+1) + '-' + pad(dt.getDate());
Another common way to do this is:
var dt = // whatever Date object you get from the control
dt.setHours(dt.getHours() + 12); // adjust to noon
dt.setMinutes(dt.getMinutes() - dt.getTimezoneOffset()); // adjust for the time zone
var dob = dt.toISOString().substring(0,10); // just get the date portion
On the Rails side of things, use a Date object instead of a DateTime. Unlike JavaScript, the Rails Date object is a date-only object - which is perfect for a date-of-birth.
I hardcode a trial expiration date in my .net 2.5 app. how do I compare it with the user's system date such that the comparison is accurate regardless of the user's culture settings?
DateTime maxTrialDate = DateTime.Parse("11/17/2020", new System.Globalization.CultureInfo("en-US"));
DateTime curDate = DateTime.Parse(DateTime.Now.ToShortDateString(), new System.Globalization.CultureInfo("en-US"));
//the next line of code uses the DateDiff method to compare the two dates -dont recall its //exact syntax.
On my XP machine the above works if the control panel regional setting for datetime is en-US, but if I change it to en-AU, then the above code that sets curDate fires a FormatException "Date is not in a correct string format"
If you avoid using strings to represent the dates, you will not encounter this problem:
DateTime maxTrialDate = new DateTime(2020, 11, 17);
if (DateTime.Now.Date > maxTrialDate)
{
// expired
}
The DateTime is created by explicitly defining the day, month and year components, so the regional settings will not confuse matters.
What about just using CultureInfo.InvariantCulture all over the place?
You can use System.Globalization.CultureInfo.InvariantCulture
If I remember correctly, in most places outside the US, the standard date format is dd/mm/yyyy, rather than the US standard of mm/dd/yyyy. It might be that when trying to parse the date, it believes the 17 is the month, which is an invalid month, thus causing the error.
Why are you using the Parse method if you are hardcoding expiration date just compare it to
DateTime.now
The FormatException is expected since you explicitly ask the parser to use en-US.
Try calling the one-argument overload of DateTime.Parse(), or alternatively, if you really want to use the two-args overload (*cough*FxCop*cough*), something like:
using System.Globalization;
DateTime.Parse("11/17/2020", CultureInfo.CurrentCulture);