This question already has answers here:
How can I format a String, which is a date, to a new date format in Java? [duplicate]
(1 answer)
SimpleDateFormat ignoring month when parsing
(4 answers)
Closed 4 years ago.
I want to convert the date from dd-mm-yy to yy-mm-dd in scala, but I am having issues to make it happen
val format = new java.text.SimpleDateFormat("dd-mm-yyyy")
format.format(new java.util.Date())
output:
res0: String = 06-07-2018
but if I want to change the format to yy-mm-dd:
val format = new java.text.SimpleDateFormat("yy-mm-dd")
format.format(new java.util.Date())
output:
res2: String = 18-41-06
what did I do wrong? why the mm comes out as 41?
The correct format is
val format = new java.text.SimpleDateFormat("yyyy-MM-dd")
what did I do wrong?
IMHO three things:
You used the long outdated Date class and the equally outdated and notoriously troublesome SimpleDateFormat. Instead use java.time, the modern Java date and time API.
You tried to roll your own date format. For most purposes your users will be happier with Java’s built-in date formats, and they save you the error-prone writing of your own format pattern string.
As others have already said, you used lowercase mm in the format pattern string. This is for minute of hour (format pattern letters are case sensitive). Apparently by coincidence you ran your first snippet at 7 minutes past the hour so it happened to agree with the current month (July).
Allow me first to demonstrate that java.time is a bit more helpful if you insist on writing your own format pattern and happen to use the wrong case (which happens for most of us from time to time). Sorry I cannot write Scala, you will have to do with Java.
DateTimeFormatter dateFormatterWithWrongCase
= DateTimeFormatter.ofPattern("dd-mm-yyyy");
LocalDate.now(ZoneId.of("America/Chicago")).format(dateFormatterWithWrongCase);
This throws the following:
java.time.temporal.UnsupportedTemporalTypeException: Unsupported field: MinuteOfHour
It tells us we were trying to do something with the minute of hour, which we certainly didn’t intend. While it may not make the cause of the error very obvious at a glance, I prefer this by far over just getting an incorrect result. And the message is rather precise when you think about it since a LocalDate is a date without time of day and therefore doesn’t have minute of hour.
For getting a nice short date format for your users I suggest:
DateTimeFormatter dateFormatter = DateTimeFormatter
.ofLocalizedDate(FormatStyle.SHORT)
.withLocale(Locale.CANADA_FRENCH);
System.out.println(LocalDate.now(ZoneId.of("America/Chicago")).format(dateFormatter));
Today this printed:
18-07-07
One advantage (and I do mean an advantage) is that the output may be different in a different locale. If I use Locale.US, I get (M/d/yy):
7/7/18
To use the default locale of your JVM either specify Locale.getDefault() or just leave out the withLocale call on the formatter.
Related
I am having an issue with converting an integer date (20180525) to a date in the format of YYYY-MM-DD. Is there a way to do this or should I just convert it in code (Java in this case)? Any help with this would be most appreciated. Thank you!
if your dates are stored as integers with YYYYMMDD, you can pass it to the date function by first casting to TEXT.
SELECT date(20180525::TEXT)
otherwise, use the function to_date with a date formatter:
SELECT to_date(20180525::text, 'YYYYMMDD')
tl;dr
Either SQL or Java works well. For SQL, see the correct Answer by Ali.
For Java, pass a LocalDate to a PreparedStatement query.
LocalDate.parse( // `LocalDate` represents a date-only value without time-of-day and without time zone. Works with SQL-standard `DATE` type.
Integer.toString( 20180525 ) , // Convert integer to text, for a `String` object as input.
DateTimeFormatter.BASIC_ISO_DATE // Specify a formatting pattern to match our input string.
) // Returns a `LocalDate` object.
2018-05-25
java.time
Regarding Java mentioned in the Question, here is code using the modern java.time classes. Whether you should use SQL or Java to parse you string depends on your situation and your tastes, as either route works.
LocalDate
The LocalDate class represents a date-only value without time-of-day and without time zone.
You need to specify a formatting pattern to match your input. In this particular case, your input string is in standard ISO 8601 format. Specifically, the “basic” variant of ISO 8601 formats that minimize the use of delimiters. In java.time, you will find this particular formatting pattern is conveniently predefined for you.
String input = Integer.toString( 20180525 ) ; // Convert integer to text for input as `String`.
DateTimeFormatter f = DateTimeFormatter.BASIC_ISO_DATE ;
LocalDate ld = LocalDate.parse( input , f ) ;
ld.toString(): 2018-05-25
JDBC
As of JDBC 4.2 and later, you can directly exchange java.time objects with your database. Always better to use smart objects rather than dumb strings.
String sql = "SELECT event_date FROM tbl WHERE event_date = ? ; " ;
…
myPreparedStatement.setObject( 1 , ld ) ;
And retrieval.
LocalDate ld = myResultSet.getObject( … , LocalDate.class ) ;
About java.time
The java.time framework is built into Java 8 and later. These classes supplant the troublesome old legacy date-time classes such as java.util.Date, Calendar, & SimpleDateFormat.
The Joda-Time project, now in maintenance mode, advises migration to the java.time classes.
To learn more, see the Oracle Tutorial. And search Stack Overflow for many examples and explanations. Specification is JSR 310.
You may exchange java.time objects directly with your database. Use a JDBC driver compliant with JDBC 4.2 or later. No need for strings, no need for java.sql.* classes.
Where to obtain the java.time classes?
Java SE 8, Java SE 9, Java SE 10, and later
Built-in.
Part of the standard Java API with a bundled implementation.
Java 9 adds some minor features and fixes.
Java SE 6 and Java SE 7
Much of the java.time functionality is back-ported to Java 6 & 7 in ThreeTen-Backport.
Android
Later versions of Android bundle implementations of the java.time classes.
For earlier Android (<26), the ThreeTenABP project adapts ThreeTen-Backport (mentioned above). See How to use ThreeTenABP….
The ThreeTen-Extra project extends java.time with additional classes. This project is a proving ground for possible future additions to java.time. You may find some useful classes here such as Interval, YearWeek, YearQuarter, and more.
select ((field_int)::text)::date as field_date from your_table;
how can i subtract number of days (timestamp|date'z') from current day (date('z')) in latte? I've tryes to use var but that does not like the formating (z).
Latte filters, unlike function calls, are not something that can be applied to any part of an expression – they are only optional feature of the variable printing macro.
{expression_to_be_printed|filter1|filter2|filter3}
date filter mostly just calls format method so you can use it directly:
{(new DateTime())->format('z') - $timestamp->format('z')}
This, however, will not work if the $timestamp lies in a different year.
To fix this, you can use DateTime’s diff method. DateInterval, returned by the method, can then be formatted using format method which provides difference in the number of days through %a formatting string.
{$timestamp->diff(new DateTime())->format('%a')}
Fortunately, the date filter also allows formatting intervals.
{$timestamp->diff(new DateTime())|date:'%a'}
Admittedly, this looks kind of ugly. A better way would be to define a custom filter so you could just use {$post->timestamp|daysAgo}. See Latte docs about creating your own filters.
As the title reads, how can I convert a UNIX timestamp, e.g. 1458297862, into a Date object in Elm?
Date.fromString does not seem to accept it, and Date.fromTime gives the wrong answer.
You can use Date.fromTime, but you have to multiply that value by 1000.
This gives you the date you'd expect:
Date.fromTime 1458297862000
I came across this answer and it didn't quite work in 0.18.
I found that Date.fromTime wouldn't accept arbitrary integers. The reason is that it's expecting floats, so you'd really want:
Date.fromTime (toFloat 1458297862000)
I'm trying to make a FromJSON instance for Data.Time.Calendar's Day type. I am confused about the types, and this seems like a common enough situation that it ought to be solved.
So the Day type represents a modified Julian date. And the Data.Time.Calendar module defines "showGregorian", which converts the modified Julian date into a Gregorian date and outputs a String ISO 8601 representation.
The trouble is that Data.Time.Calendar doesn't have a good way to parse an ISO 8601 into a Gregorian date. If I use the ParseTime class, I can only pass in the string format, and not the calendar for which the string is a representation of a date. So, effectively, I'd pass in '20140502' and the ParseTime class would treat that string as the string representation of a modified Julian date.
It seems like this ought to be a solved problem. Ideally, I'd like a solution that does not use date-times. My model uses Gregorian calendar dates because that is all I need, and those are the things I will be comparing, searching, etc.
Of course, the whole reason for using calendar days when I only need calendar days was so that I wouldn't have to think about how to compare and convert them, but I suppose that is a whine for another day.
Addendum:
Days are defined as:
-- | The Modified Julian Day is a standard count of days, with zero being the day 1858-11-17.
newtype Day = ModifiedJulianDay {toModifiedJulianDay :: Integer} deriving (Eq,Ord)
This lead me to believe that a Day is not a physical day, but a day in the MJD calendar (under the principle that the exposed documentation should tell us what a type represents, not the representation for the type).
Why doesn't parseTime do exactly what you want? parseTime defaultTimeLocale "%F" is exactly the inverse (up to Just) of showGregorian, as demonstrated by the following snippet that you can paste into GHCi.
import System.Locale
import Data.Time.Format
import Data.Time.Calendar
let test = parseTime defaultTimeLocale "%F" . showGregorian :: Day -> Maybe Day
let notIdentity x = case test x of { Nothing -> True; Just x' -> x /= x' }
filter notIdentity [fromGregorian 0 1 1..fromGregorian 3000 12 31]
The GHC.Generics module is making this type of problem very easy to solve.
{-# language DeriveGeneric #-}
{-# language StandaloneDeriving #-}
import Data.Aeson
import Data.Time.Calendar
import GHC.Generics
deriving instance Generic Day
instance ToJSON Day
instance FromJSON Day
Though on reading your comment:
The thing I'm after is a bugless way to parse an ISO 8601 date into a 'Day', which uses the modified Julian calendar.
This may not be the solution you are looking for.
I am using nscala-time (wrapper for Joda Time) and slick for a project. I'm trying to use this clause to write a line to the database:
Article.insert(0,"title1", "hellothere", DateTime.now.getMillis.asInstanceOf[Timestamp])
Apparently Slick does not support "dateTime" type defined in Joda Time, and I have to use java.sql.Timestamp instead. So I decide to do a little conversion inside the insert method, using "asInstanceOf". Unfortunately, Scala quickly tells me that Java.Long cannot be converted to Java.sql.Timestamp. Then I used this:
val dateTime = new DateTime();
val timeStamp = new Timestamp(dateTime.getMillis());
Article.insert(0,"title1", "hellothere", timeStamp)
This magically works, and all I'm left with is confusion.
How can I convert it one way but not the other? Should I use a different conversion than asInstanceOf?
You misunderstand what asInstanceOf does: asInstanceOf doesn't convert anything. What it does is lie to the compiler, telling it to believe something instead of going with the knowledge it has.
So, you had a Long, and then you got a Long, but pretended it was a Timestamp, which obviously doesn't work.
I have a simple recommendation regarding asInstanceOf: never use it.
There's no magic about it. Your first statement:
DateTime.now.getMillis
is a Long. A Long is not a Timestamp, so it makes sense that you can't convert it to one by using asInstanceOf.
The second statement:
new Timestamp(dateTime.getMillis())
is using the Timestamp constructor to create a new Timestamp instance based on the dateTime.getMillis.