How would one build a list of all Fridays in 2011, and allow for different date output, e.g. mm/dd/yyyy and yyyymmdd?
An alternative to ataylor's correct answer, you could do:
import static java.util.Calendar.*
def s = Date.parse("MM/dd/yyyy", "01/01/2011")
def e = Date.parse("MM/dd/yyyy", "12/31/2011")
(s..e).findAll {
it[ DAY_OF_WEEK ] == FRIDAY
}.each {
println it.format("MM/dd/yyyy")
}
I'd go with something like this:
use (groovy.time.TimeCategory) {
def d = Date.parse("MM/dd/yyyy", "01/01/2011")
while (d[Calendar.DAY_OF_WEEK] != Calendar.FRIDAY) {
d = d + 1.day
}
while (d[Calendar.YEAR] == 2011) {
println d.format("MM/dd/yyyy")
d = d + 1.week
}
}
Both ataylor's answer and Tim's answer are correct and very informative -- see comments if you're coming up to speed on Groovy.
I hate these situations where I'm supposed to pick one as the answer over the other. They are both right answers. Stackoverflow won't change their stuff so I can select both as correct, so I will merely point to both as being correct.
Related
I am doing an activity to learn Kotlin where I am completely stuck. I am new to coding and Kotlin so excuse me for my mistakes and lack of knowledge.
This is the description of the activity:
You need to write a program that prints date and time in a special format. Hours, minutes and seconds are split by a colon, and day, month and year are split by a slash. For example:
Sample Input 1:
23 59 59
12 12 2018
Sample Output 1:
23:59:59 12/12/2018
I have been trying a lot of different things, but I'm lost. This is the path that I was trying to take:
fun main() {
val time = readLine()?.split("")
val date = readLine()?.split("")
println("$time $date")
}
I know the code is wrong, as I don't know how to do it, I am simply posting the path or idea that I was following. If someone could explain me what I have to do, I would really appreciate it. Thanks!
Try to edit your code like this
fun main() {
val time = readLine()?.split(" ")?.joinToString(":") ?: ""
val date = readLine()?.split(" ")?.joinToString("/") ?: ""
println("$time $date")
}
If you'd like to check if the read line is actually a date you can use DateTimeFormatter
private fun parseDate(arg: String) {
try {
val timeString = arg.split(" ").take(3).joinToString(":")
val dateString = arg.split(" ").takeLast(3).joinToString("/")
val parser = DateTimeFormatter.ofPattern("dd/MM/yyyy HH:mm:ss")
parser.parse("$dateString $timeString")
println("$dateString $timeString")
} catch (e: Exception) {
println("[ERR] - Error parsing argument: $arg")
}
}
fun main() {
parseDate(readLine())
}
I am fairly new to the Groovy/Grails arena. I recently modified some code to add the following block.
result.processed.each{
def queueEntry = QueueEntry.findById(it.id)<<<START ADD>>>
Set dates = new HashSet<Long>()
def children = QueueEntry.findAllByParent(queueEntry)
for(QueueEntry qe : children){
def f = new GregorianCalendar()
f.setTimeInMillis(DateUtils.getClearedTime(qe.entryTimestamp))
def l = new GregorianCalendar()
l.setTimeInMillis(DateUtils.getClearedTime(qe.exitTimestamp))
while(f < l){
if(f.get(Calendar.DAY_OF_WEEK) != Calendar.SUNDAY && f.get(Calendar.DAY_OF_WEEK) != Calendar.SATURDAY){//only add weekdays
dates.add(f.time.time)
}
def xx = new GregorianCalendar()
xx.setTimeInMillis(f.time.next().time)
f = xx
}
dates.add(l.time.time)
} <<<STOP ADD>>>
Set outsideDays = it.numberOfDaysOutsideCVB
Set days = DateUtils.businessDaysBetweenDates(it.entryTimestamp, it.exitTimestamp)
days.removeAll(outsideDays)
days.removeAll(dates)
turnTimes << days.size()
}
The application is now crawling. I am obviously doing something wrong. When this is run for small data-sets it will complete slowly. On larger sets it doesn't finish. Prior to this change it was completing.
You can start with the lines of the below changes.
// Proposed
import static java.util.Calendar.*
// Query for all the children upfront instead of hitting
// database twice on each iteration.
// You can also avoid N + 1 situation if children is fetched eagerly
def allChildren = QueueEntry.where {
id in (result.processed*.id as List<Long>)
}.children.list()
def turnTimes = result.processed.collect { entry ->
allChildren.findAll { it.parent.id == entry.id }.collect { child ->
Set dates = []
new Date( child.entryTimeStamp ).upto( new Date( child.exitTimestamp ) ) {
if ( !( it[DAY_OF_WEEK] in [ SUNDAY, SATURDAY ] ) ) {
dates << it.time
}
}
Set outsideDays = child.numberOfDaysOutsideCVB
Set days =
DateUtils.businessDaysBetweenDates(
child.entryTimestamp,
child.exitTimestamp
)
( days - outsideDays - dates )?.size() ?: 0
}
}
Assumptions:
QueueEntry hasMany children
entryTimestamp/exitTimestamp is java.sql.Timestamp
entryTimestamp/exitTimestamp are not null and entryTimestamp comes before exitTimestamp.
As Burt suggested this question best fits in codereview.stackexchange.com
When try this sample code:
use(groovy.time.TimeCategory) {
800.millisecond + 300.millisecond
}
in groovy web console, I get a funny result:
0.1100 seconds
Does any one know why this happens or how to fix it?
That looks like a bug, the TimeDuration contains 1100 milliseconds, but when it prints it out, it converts it wrongly to seconds.
I've added it to the Groovy JIRA as a bug EDIT It's now marked as FIXED for versions 2.0.6, 1.8.9 and 2.1.0
In the mean time, I guess you'll need to do your own converter from TimeDuration to String :-/
Edit
You could do something like this (and there is probably a neater way of doing it)
groovy.time.TimeDuration.metaClass.normalize = { ->
def newdmap = ['days','hours','minutes','seconds','millis'].collectEntries {
[ (it):delegate."$it" ]
}.with { dmap ->
[millis:1000,seconds:60,minutes:60,hours:24,days:-1].inject( [ dur:[ days:0, hours:0, minutes:0, seconds:0, millis:0 ], roll:0 ] ) { val, field ->
val.dur."$field.key" = dmap."$field.key" + val.roll
val.roll = val.dur."$field.key".intdiv( field.value )
val.dur."$field.key" = field.value < 0 ?
val.dur."$field.key" :
val.dur."$field.key" % field.value
val
}.dur
}
new TimeDuration( newdmap.days, newdmap.hours, newdmap.minutes, newdmap.seconds, newdmap.millis )
}
That adds a normalize method to TimeDuration, so then doing:
use(groovy.time.TimeCategory) {
800.millisecond + 300.millisecond
}.normalize()
Shows 1.100 seconds
I haven't done a huge amount of testing on that method, so be warned it could do with some unit tests to make sure it doesn't fall over with other situations.
Just started learning Groovy, got the PragProg book "Programming Groovy" and had a problem compiling one of the sample scripts:
class GCar2 {
final miles = 0
def getMiles() {
println "getMiles called"
miles
}
def drive(dist) {
if (dist > 0) {
miles += dist
}
}
}
def car = new GCar2()
println "Miles: $car.miles"
println 'Driving'
car.drive(10)
println "Miles: $car.miles"
try {
print 'Can I see the miles? '
car.miles = 12
} catch (groovy.lang.ReadOnlyPropertyException ex) {
println ex.message
GroovyCar2.groovy: 20: cannnot access final field or property outside of constructor.
# line 20, column 35.
def drive(dist) { if (dist > 0) miles += dist }
^
Groovy versions prior to 1.7 do not give an error. I looked through whatever documentation I could find and did not see the issue discussed. What is going on here?
Aaron
I don't know much about Groovy 1.7, but it looks like a bug in earlier versions which has now been fixed - if a variable is final, you shouldn't be able to assign to it outside the constructor (or its declaration). If you can, what's the point of making it final?
I doubt that it'll stop you from reading it outside the constructor though...
You shouldn't be able to assign to a final variable in a normal method. It was a bug in groovy, fixed in 1.7.
are there any improvements where i can improve this code? Maybe there are some groovy language features? This snippet flattens a xml file to: node/node/node
def root = new XmlParser().parse("src/your_xml.xml")
root.depthFirst().each { n ->
def name = n.name()
while(n?.parent()){
name = "${n?.parent()?.name()}/${name}";
n = n?.parent()
}
println name
}
I might refactor the code to use a more functional style.
def x = """
<test>
<test1>
<test2/>
</test1>
<test2>
<test3/>
<test4>
<test5/>
</test4>
</test2>
</test>
""".trim()
def root = new XmlParser().parseText(x)
def nodePath(node) {
node.parent() ? "${nodePath(node.parent())}/${node.name()}" : node.name()
}
root.depthFirst().each {
println nodePath(it)
}
assert nodePath(root.test2[0].test4[0].test5[0]) == "test/test2/test4/test5"
-- Edit: Ignore me, I'm wrong [see comments] (not the last line though);
I suspect you can write (but I could be wrong, I have no experience with this language)
while(n = n?.parent()){
But honestly; don't go with something that is cool, go with something that is readable.